Tarantool development patches archive
 help / color / mirror / Atom feed
* [tarantool-patches] [PATCH] test: fix flaky socket test
@ 2019-08-30 15:28 Ilya Kosarev
  0 siblings, 0 replies; 9+ messages in thread
From: Ilya Kosarev @ 2019-08-30 15:28 UTC (permalink / raw)
  To: tarantool-patches; +Cc: georgy, alexander.turenko, avtikhon, Ilya Kosarev

socket.test had a number of problems:
- racing condition on closing socket around line 640
- racing condition on waiting around line 42
- racing conditions on "receiving_socket:recv" around line 777
Now they are solved.

Closes #4451, #4426
---
Branch: https://github.com/tarantool/tarantool/tree/i.kosarev/gh-4426-4451-fix-socket-test
Issues: https://github.com/tarantool/tarantool/issues/4426 https://github.com/tarantool/tarantool/issues/4451

 test/app/socket.result   | 43 +++++++++++++++++++++++++++++++++-------
 test/app/socket.test.lua | 22 ++++++++++++++++----
 2 files changed, 54 insertions(+), 11 deletions(-)

diff --git a/test/app/socket.result b/test/app/socket.result
index fd299424c..811f6b4e9 100644
--- a/test/app/socket.result
+++ b/test/app/socket.result
@@ -107,11 +107,11 @@ s:nonblock(true)
 ---
 - true
 ...
-s:readable(.1)
+s:readable(.5)
 ---
 - true
 ...
-s:wait(.1)
+s:wait(.5)
 ---
 - RW
 ...
@@ -1822,8 +1822,14 @@ test_run:cmd("setopt delimiter ';'")
 ---
 - true
 ...
+socket_opened = true
 cfiber = fiber.create(function(sc, rch, wch)
-    while sc:send(wch:get()) and rch:put(sc:receive("*l")) do end
+    while socket_opened do
+        sc:send(wch:get())
+        local data = sc:receive("*l")
+        if not socket_opened then sc:close() end
+        rch:put(data)
+    end
 end, sc, rch, wch);
 ---
 ...
@@ -1936,6 +1942,9 @@ c:receive("*l")
 ---
 - 
 ...
+socket_opened = false
+---
+...
 wch:put("Fu")
 ---
 - true
@@ -1944,10 +1953,6 @@ c:send("354 Please type your message\n")
 ---
 - 29
 ...
-sc:close()
----
-- 1
-...
 c:receive("*l", "Line: ")
 ---
 - null
@@ -2292,6 +2297,9 @@ sendto_zero(sending_socket, '127.0.0.1', receiving_socket_port)
 ---
 - 0
 ...
+fiber.yield()
+---
+...
 received_message = receiving_socket:recv()
 ---
 ...
@@ -2315,6 +2323,9 @@ sendto_zero(sending_socket, '127.0.0.1', receiving_socket_port)
 ---
 - 0
 ...
+fiber.yield()
+---
+...
 received_message, from = receiving_socket:recvfrom()
 ---
 ...
@@ -2392,6 +2403,9 @@ sendto_zero(sending_socket, '127.0.0.1', receiving_socket_port)
 ---
 - 0
 ...
+fiber.yield()
+---
+...
 received_message = receiving_socket:recv(512)
 ---
 ...
@@ -2415,6 +2429,9 @@ sendto_zero(sending_socket, '127.0.0.1', receiving_socket_port)
 ---
 - 0
 ...
+fiber.yield()
+---
+...
 received_message, from = receiving_socket:recvfrom(512)
 ---
 ...
@@ -2452,6 +2469,9 @@ sending_socket:sendto('127.0.0.1', receiving_socket_port, message)
 ---
 - 1025
 ...
+fiber.yield()
+---
+...
 received_message = receiving_socket:recv()
 ---
 ...
@@ -2484,6 +2504,9 @@ sending_socket:sendto('127.0.0.1', receiving_socket_port, message)
 ---
 - 1025
 ...
+fiber.yield()
+---
+...
 received_message, from = receiving_socket:recvfrom()
 ---
 ...
@@ -2523,6 +2546,9 @@ sending_socket:sendto('127.0.0.1', receiving_socket_port, message)
 ---
 - 1025
 ...
+fiber.yield()
+---
+...
 received_message = receiving_socket:recv(512)
 ---
 ...
@@ -2566,6 +2592,9 @@ sending_socket:sendto('127.0.0.1', receiving_socket_port, message)
 ---
 - 1025
 ...
+fiber.yield()
+---
+...
 received_message, from = receiving_socket:recvfrom(512)
 ---
 ...
diff --git a/test/app/socket.test.lua b/test/app/socket.test.lua
index c72d41763..8cb693735 100644
--- a/test/app/socket.test.lua
+++ b/test/app/socket.test.lua
@@ -39,8 +39,8 @@ s:nonblock(false)
 s:nonblock()
 s:nonblock(true)
 
-s:readable(.1)
-s:wait(.1)
+s:readable(.5)
+s:wait(.5)
 socket.iowait(s:fd(), 'RW')
 socket.iowait(s:fd(), 3)
 socket.iowait(s:fd(), 'R')
@@ -619,8 +619,14 @@ s:settimeout(100500)
 rch, wch = fiber.channel(1), fiber.channel(1)
 sc = socket.connect(host, port)
 test_run:cmd("setopt delimiter ';'")
+socket_opened = true
 cfiber = fiber.create(function(sc, rch, wch)
-    while sc:send(wch:get()) and rch:put(sc:receive("*l")) do end
+    while socket_opened do
+        sc:send(wch:get())
+        local data = sc:receive("*l")
+        if not socket_opened then sc:close() end
+        rch:put(data)
+    end
 end, sc, rch, wch);
 test_run:cmd("setopt delimiter ''");
 
@@ -651,9 +657,9 @@ rch:get()
 wch:put("DATA\n")
 c:receive(4)
 c:receive("*l")
+socket_opened = false
 wch:put("Fu")
 c:send("354 Please type your message\n")
-sc:close()
 c:receive("*l", "Line: ")
 c:receive()
 c:receive(10)
@@ -778,6 +784,7 @@ e == errno.EAGAIN -- expected true
 
 -- case: recv, zero datagram
 sendto_zero(sending_socket, '127.0.0.1', receiving_socket_port)
+fiber.yield()
 received_message = receiving_socket:recv()
 e = receiving_socket:errno()
 received_message == '' -- expected true
@@ -786,6 +793,7 @@ e == 0 -- expected true
 
 -- case: recvfrom, zero datagram
 sendto_zero(sending_socket, '127.0.0.1', receiving_socket_port)
+fiber.yield()
 received_message, from = receiving_socket:recvfrom()
 e = receiving_socket:errno()
 received_message == '' -- expected true
@@ -812,6 +820,7 @@ e == errno.EAGAIN -- expected true
 
 -- case: recv, zero datagram, explicit size
 sendto_zero(sending_socket, '127.0.0.1', receiving_socket_port)
+fiber.yield()
 received_message = receiving_socket:recv(512)
 e = receiving_socket:errno()
 received_message == '' -- expected true
@@ -820,6 +829,7 @@ e == 0 -- expected true
 
 -- case: recvfrom, zero datagram, explicit size
 sendto_zero(sending_socket, '127.0.0.1', receiving_socket_port)
+fiber.yield()
 received_message, from = receiving_socket:recvfrom(512)
 e = receiving_socket:errno()
 received_message == '' -- expected true
@@ -833,6 +843,7 @@ message = string.rep('x', message_len)
 
 -- case: recv, non-zero length datagram, the buffer size should be evaluated
 sending_socket:sendto('127.0.0.1', receiving_socket_port, message)
+fiber.yield()
 received_message = receiving_socket:recv()
 e = receiving_socket:errno()
 received_message == message -- expected true
@@ -844,6 +855,7 @@ e
 -- case: recvfrom, non-zero length datagram, the buffer size should be
 -- evaluated
 sending_socket:sendto('127.0.0.1', receiving_socket_port, message)
+fiber.yield()
 received_message, from = receiving_socket:recvfrom()
 e = receiving_socket:errno()
 received_message == message -- expected true
@@ -856,6 +868,7 @@ e
 
 -- case: recv truncates a datagram larger then the buffer of an explicit size
 sending_socket:sendto('127.0.0.1', receiving_socket_port, message)
+fiber.yield()
 received_message = receiving_socket:recv(512)
 e = receiving_socket:errno()
 received_message == message:sub(1, 512) -- expected true
@@ -872,6 +885,7 @@ message = string.rep('y', message_len)
 
 -- case: recvfrom truncates a datagram larger then the buffer of an explicit size
 sending_socket:sendto('127.0.0.1', receiving_socket_port, message)
+fiber.yield()
 received_message, from = receiving_socket:recvfrom(512)
 e = receiving_socket:errno()
 received_message == message:sub(1, 512) -- expected true
-- 
2.17.1

^ permalink raw reply	[flat|nested] 9+ messages in thread
* [Tarantool-patches] [PATCH] test: fix flaky socket test
@ 2019-11-26  1:19 Ilya Kosarev
  0 siblings, 0 replies; 9+ messages in thread
From: Ilya Kosarev @ 2019-11-26  1:19 UTC (permalink / raw)
  To: tarantool-patches

socket.test had a number of flaky problems:
- socket readableness expectation
- race conditions on socket shutdown in emulation test cases
- tcp_server stability in socket receive inconsistent behavior case
Now they are solved. Socket test is not fragile anymore.

Closes #4451, #4426, #4469
---
Branch: https://github.com/tarantool/tarantool/tree/i.kosarev/gh-4426-4451-fix-socket-test
Issues: https://github.com/tarantool/tarantool/issues/4426
        https://github.com/tarantool/tarantool/issues/4451
        https://github.com/tarantool/tarantool/issues/4469

 test/app/socket.result   | 52 +++++++++++++++++++++++++++++-----------
 test/app/socket.test.lua | 34 +++++++++++++++++---------
 test/app/suite.ini       |  1 -
 3 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/test/app/socket.result b/test/app/socket.result
index fd299424c..d6250a796 100644
--- a/test/app/socket.result
+++ b/test/app/socket.result
@@ -45,6 +45,9 @@ test_run:cmd("push filter '(error: .builtin/.*[.]lua):[0-9]+' to '\\1'")
 WAIT_COND_TIME = 10
 ---
 ...
+WAIT_TCP_CONNECT_TIME = 240
+---
+...
 socket('PF_INET', 'SOCK_STREAM', 'tcp121222');
 ---
 - null
@@ -107,7 +110,7 @@ s:nonblock(true)
 ---
 - true
 ...
-s:readable(.1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -227,7 +230,7 @@ s:syswrite(ffi.cast('const char *', ping), #ping)
 ---
 - 6
 ...
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -830,7 +833,7 @@ sc:sendto('127.0.0.1', s:name().port, 'Hello, world')
 ---
 - 12
 ...
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -842,7 +845,7 @@ sc:sendto('127.0.0.1', s:name().port, 'Hello, world, 2')
 ---
 - 15
 ...
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -898,7 +901,7 @@ sc:sendto('127.0.0.1', s:name().port, 'Hello, World!')
 ---
 - 13
 ...
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -1092,7 +1095,7 @@ test_run:wait_cond(function()
         return false, master:error()
     end
     return true
-end, WAIT_COND_TIME);
+end, 100);
 ---
 - true
 ...
@@ -1822,8 +1825,14 @@ test_run:cmd("setopt delimiter ';'")
 ---
 - true
 ...
+socket_opened = true
 cfiber = fiber.create(function(sc, rch, wch)
-    while sc:send(wch:get()) and rch:put(sc:receive("*l")) do end
+    while socket_opened do
+        sc:send(wch:get())
+        local data = sc:receive("*l")
+        if not socket_opened then sc:close() end
+        rch:put(data)
+    end
 end, sc, rch, wch);
 ---
 ...
@@ -1936,6 +1945,9 @@ c:receive("*l")
 ---
 - 
 ...
+socket_opened = false
+---
+...
 wch:put("Fu")
 ---
 - true
@@ -1944,10 +1956,6 @@ c:send("354 Please type your message\n")
 ---
 - 29
 ...
-sc:close()
----
-- 1
-...
 c:receive("*l", "Line: ")
 ---
 - null
@@ -2816,20 +2824,36 @@ test_run:cmd("clear filter")
 ---
 - true
 ...
--- case: sicket receive inconsistent behavior
+-- case: socket receive inconsistent behavior
 chan = fiber.channel()
 ---
 ...
+seed = ''
+---
+...
+for d in string.gmatch(box.info.cluster.uuid, '%d') do  seed = seed .. d end
+---
+...
+math.randomseed(tonumber(seed))
+---
+...
+port = 32768 + math.random(0, 32767)
+---
+...
 counter = 0
 ---
 ...
 fn = function(s) counter = 0; while true do s:write((tostring(counter)):rep(chan:get())); counter = counter + 1 end end
 ---
 ...
-srv = socket.tcp_server('0.0.0.0', 8888, fn)
+srv = nil
 ---
 ...
-s = socket.connect('localhost', 8888)
+test_run:wait_cond(function() srv = socket.tcp_server('0.0.0.0', port, fn); return srv ~= nil end, 100)
+---
+- true
+...
+s = socket.connect('localhost', port)
 ---
 ...
 chan:put(5)
diff --git a/test/app/socket.test.lua b/test/app/socket.test.lua
index c72d41763..413d0b065 100644
--- a/test/app/socket.test.lua
+++ b/test/app/socket.test.lua
@@ -14,6 +14,7 @@ test_run = env.new()
 test_run:cmd("push filter '(error: .builtin/.*[.]lua):[0-9]+' to '\\1'")
 
 WAIT_COND_TIME = 10
+WAIT_TCP_CONNECT_TIME = 240
 
 socket('PF_INET', 'SOCK_STREAM', 'tcp121222');
 
@@ -39,7 +40,7 @@ s:nonblock(false)
 s:nonblock()
 s:nonblock(true)
 
-s:readable(.1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 s:wait(.1)
 socket.iowait(s:fd(), 'RW')
 socket.iowait(s:fd(), 3)
@@ -75,7 +76,7 @@ ping = msgpack.encode(string.len(ping)) .. ping
 
 -- test syswrite with char *
 s:syswrite(ffi.cast('const char *', ping), #ping)
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 s:wait(.01)
 
 pong = s:sysread()
@@ -266,11 +267,11 @@ s = socket('AF_INET', 'SOCK_DGRAM', 'udp')
 s:bind('127.0.0.1', 0)
 sc = socket('AF_INET', 'SOCK_DGRAM', 'udp')
 sc:sendto('127.0.0.1', s:name().port, 'Hello, world')
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 s:recv()
 
 sc:sendto('127.0.0.1', s:name().port, 'Hello, world, 2')
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 d, from = s:recvfrom()
 from.port > 0
 from.port = 'Random port'
@@ -286,7 +287,7 @@ sc = socket('AF_INET', 'SOCK_DGRAM', 'udp')
 sc:nonblock(true)
 sc:sendto('127.0.0.1', s:name().port)
 sc:sendto('127.0.0.1', s:name().port, 'Hello, World!')
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 data, from = s:recvfrom(10)
 data
 s:sendto(from.host, from.port, 'Hello, hello!')
@@ -356,7 +357,7 @@ test_run:wait_cond(function()
         return false, master:error()
     end
     return true
-end, WAIT_COND_TIME);
+end, 100);
 function gh361()
     local s = socket('PF_INET', 'SOCK_STREAM', 'tcp')
     s:sysconnect('127.0.0.1', port)
@@ -619,8 +620,14 @@ s:settimeout(100500)
 rch, wch = fiber.channel(1), fiber.channel(1)
 sc = socket.connect(host, port)
 test_run:cmd("setopt delimiter ';'")
+socket_opened = true
 cfiber = fiber.create(function(sc, rch, wch)
-    while sc:send(wch:get()) and rch:put(sc:receive("*l")) do end
+    while socket_opened do
+        sc:send(wch:get())
+        local data = sc:receive("*l")
+        if not socket_opened then sc:close() end
+        rch:put(data)
+    end
 end, sc, rch, wch);
 test_run:cmd("setopt delimiter ''");
 
@@ -651,9 +658,9 @@ rch:get()
 wch:put("DATA\n")
 c:receive(4)
 c:receive("*l")
+socket_opened = false
 wch:put("Fu")
 c:send("354 Please type your message\n")
-sc:close()
 c:receive("*l", "Line: ")
 c:receive()
 c:receive(10)
@@ -960,12 +967,17 @@ server:close()
 
 test_run:cmd("clear filter")
 
--- case: sicket receive inconsistent behavior
+-- case: socket receive inconsistent behavior
 chan = fiber.channel()
+seed = ''
+for d in string.gmatch(box.info.cluster.uuid, '%d') do  seed = seed .. d end
+math.randomseed(tonumber(seed))
+port = 32768 + math.random(0, 32767)
 counter = 0
 fn = function(s) counter = 0; while true do s:write((tostring(counter)):rep(chan:get())); counter = counter + 1 end end
-srv = socket.tcp_server('0.0.0.0', 8888, fn)
-s = socket.connect('localhost', 8888)
+srv = nil
+test_run:wait_cond(function() srv = socket.tcp_server('0.0.0.0', port, fn); return srv ~= nil end, 100)
+s = socket.connect('localhost', port)
 chan:put(5)
 chan:put(5)
 s:receive(5)
diff --git a/test/app/suite.ini b/test/app/suite.ini
index 79432e29a..dd802d98c 100644
--- a/test/app/suite.ini
+++ b/test/app/suite.ini
@@ -7,4 +7,3 @@ use_unix_sockets = True
 use_unix_sockets_iproto = True
 is_parallel = True
 pretest_clean = True
-fragile = socket.test.lua ; gh-4426 gh-4451
-- 
2.17.1

^ permalink raw reply	[flat|nested] 9+ messages in thread
* [Tarantool-patches] [PATCH] test: fix flaky socket test
@ 2019-11-26 21:45 Ilya Kosarev
  0 siblings, 0 replies; 9+ messages in thread
From: Ilya Kosarev @ 2019-11-26 21:45 UTC (permalink / raw)
  To: tarantool-patches

socket.test had a number of flaky problems:
- socket readableness expectation
- race conditions on socket shutdown in emulation test cases
- tcp_server stability in socket receive inconsistent behavior case
Now they are solved. Port randomization is improved.
Socket test is not fragile anymore.

Closes #4451, #4426, #4469
---
Branch: https://github.com/tarantool/tarantool/tree/i.kosarev/gh-4426-4451-fix-socket-test
Issues: https://github.com/tarantool/tarantool/issues/4426
        https://github.com/tarantool/tarantool/issues/4451
        https://github.com/tarantool/tarantool/issues/4469

 test/app/socket.result   | 84 +++++++++++++++++++++++++---------------
 test/app/socket.test.lua | 60 +++++++++++++++++++---------
 test/app/suite.ini       |  1 -
 3 files changed, 94 insertions(+), 51 deletions(-)

diff --git a/test/app/socket.result b/test/app/socket.result
index fd299424c9..42dde8f375 100644
--- a/test/app/socket.result
+++ b/test/app/socket.result
@@ -45,6 +45,9 @@ test_run:cmd("push filter '(error: .builtin/.*[.]lua):[0-9]+' to '\\1'")
 WAIT_COND_TIME = 10
 ---
 ...
+WAIT_TCP_CONNECT_TIME = 240
+---
+...
 socket('PF_INET', 'SOCK_STREAM', 'tcp121222');
 ---
 - null
@@ -107,7 +110,7 @@ s:nonblock(true)
 ---
 - true
 ...
-s:readable(.1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -227,7 +230,7 @@ s:syswrite(ffi.cast('const char *', ping), #ping)
 ---
 - 6
 ...
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -830,7 +833,7 @@ sc:sendto('127.0.0.1', s:name().port, 'Hello, world')
 ---
 - 12
 ...
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -842,7 +845,7 @@ sc:sendto('127.0.0.1', s:name().port, 'Hello, world, 2')
 ---
 - 15
 ...
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -898,7 +901,7 @@ sc:sendto('127.0.0.1', s:name().port, 'Hello, World!')
 ---
 - 13
 ...
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -1074,6 +1077,15 @@ master:setsockopt('SOL_SOCKET', 'SO_REUSEADDR', true)
 ---
 - true
 ...
+seed = ''
+---
+...
+for d in string.gmatch(box.info.uuid, '%d') do  seed = seed .. d end
+---
+...
+math.randomseed(tonumber(seed))
+---
+...
 port = 32768 + math.random(0, 32767)
 ---
 ...
@@ -1092,7 +1104,7 @@ test_run:wait_cond(function()
         return false, master:error()
     end
     return true
-end, WAIT_COND_TIME);
+end, 100);
 ---
 - true
 ...
@@ -1822,8 +1834,14 @@ test_run:cmd("setopt delimiter ';'")
 ---
 - true
 ...
+socket_opened = true
 cfiber = fiber.create(function(sc, rch, wch)
-    while sc:send(wch:get()) and rch:put(sc:receive("*l")) do end
+    while socket_opened do
+        sc:send(wch:get())
+        local data = sc:receive("*l")
+        if not socket_opened then sc:close() end
+        rch:put(data)
+    end
 end, sc, rch, wch);
 ---
 ...
@@ -1936,6 +1954,9 @@ c:receive("*l")
 ---
 - 
 ...
+socket_opened = false
+---
+...
 wch:put("Fu")
 ---
 - true
@@ -1944,10 +1965,6 @@ c:send("354 Please type your message\n")
 ---
 - 29
 ...
-sc:close()
----
-- 1
-...
 c:receive("*l", "Line: ")
 ---
 - null
@@ -2816,7 +2833,7 @@ test_run:cmd("clear filter")
 ---
 - true
 ...
--- case: sicket receive inconsistent behavior
+-- case: socket receive inconsistent behavior
 chan = fiber.channel()
 ---
 ...
@@ -2826,41 +2843,46 @@ counter = 0
 fn = function(s) counter = 0; while true do s:write((tostring(counter)):rep(chan:get())); counter = counter + 1 end end
 ---
 ...
-srv = socket.tcp_server('0.0.0.0', 8888, fn)
+srv = nil
 ---
 ...
-s = socket.connect('localhost', 8888)
+test_run:cmd("setopt delimiter ';'")
 ---
+- true
 ...
-chan:put(5)
+test_run:wait_cond(function()
+    port = 32768 + math.random(0, 32767)
+    srv = socket.tcp_server('0.0.0.0', port, fn)
+    return srv ~= nil
+end, 100);
 ---
 - true
 ...
-chan:put(5)
+receive1 = nil; receive2 = nil;
 ---
-- true
 ...
-s:receive(5)
+if srv ~= nil then
+    s = socket.connect('localhost', port)
+    chan:put(5)
+    chan:put(5)
+    receive1 = s:receive(5)
+    chan:put(5)
+    s:settimeout(1)
+    receive2 = s:receive('*a')
+    s:close()
+    srv:close()
+end;
 ---
-- '00000'
 ...
-chan:put(5)
+test_run:cmd("setopt delimiter ''");
 ---
 - true
 ...
-s:settimeout(1)
+receive1
 ---
-- 1
+- '00000'
 ...
-s:receive('*a')
+receive2
 ---
 - '1111122222'
 ...
-s:close()
----
-- 1
-...
-srv:close()
----
-- true
-...
diff --git a/test/app/socket.test.lua b/test/app/socket.test.lua
index c72d41763f..64f1e07471 100644
--- a/test/app/socket.test.lua
+++ b/test/app/socket.test.lua
@@ -14,6 +14,7 @@ test_run = env.new()
 test_run:cmd("push filter '(error: .builtin/.*[.]lua):[0-9]+' to '\\1'")
 
 WAIT_COND_TIME = 10
+WAIT_TCP_CONNECT_TIME = 240
 
 socket('PF_INET', 'SOCK_STREAM', 'tcp121222');
 
@@ -39,7 +40,7 @@ s:nonblock(false)
 s:nonblock()
 s:nonblock(true)
 
-s:readable(.1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 s:wait(.1)
 socket.iowait(s:fd(), 'RW')
 socket.iowait(s:fd(), 3)
@@ -75,7 +76,7 @@ ping = msgpack.encode(string.len(ping)) .. ping
 
 -- test syswrite with char *
 s:syswrite(ffi.cast('const char *', ping), #ping)
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 s:wait(.01)
 
 pong = s:sysread()
@@ -266,11 +267,11 @@ s = socket('AF_INET', 'SOCK_DGRAM', 'udp')
 s:bind('127.0.0.1', 0)
 sc = socket('AF_INET', 'SOCK_DGRAM', 'udp')
 sc:sendto('127.0.0.1', s:name().port, 'Hello, world')
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 s:recv()
 
 sc:sendto('127.0.0.1', s:name().port, 'Hello, world, 2')
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 d, from = s:recvfrom()
 from.port > 0
 from.port = 'Random port'
@@ -286,7 +287,7 @@ sc = socket('AF_INET', 'SOCK_DGRAM', 'udp')
 sc:nonblock(true)
 sc:sendto('127.0.0.1', s:name().port)
 sc:sendto('127.0.0.1', s:name().port, 'Hello, World!')
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 data, from = s:recvfrom(10)
 data
 s:sendto(from.host, from.port, 'Hello, hello!')
@@ -343,6 +344,9 @@ s = nil
 -- random port
 master = socket('PF_INET', 'SOCK_STREAM', 'tcp')
 master:setsockopt('SOL_SOCKET', 'SO_REUSEADDR', true)
+seed = ''
+for d in string.gmatch(box.info.uuid, '%d') do  seed = seed .. d end
+math.randomseed(tonumber(seed))
 port = 32768 + math.random(0, 32767)
 -- SO_REUSEADDR allows to bind to the same source addr:port twice,
 -- so listen() can return EADDRINUSE and so we check it within
@@ -356,7 +360,7 @@ test_run:wait_cond(function()
         return false, master:error()
     end
     return true
-end, WAIT_COND_TIME);
+end, 100);
 function gh361()
     local s = socket('PF_INET', 'SOCK_STREAM', 'tcp')
     s:sysconnect('127.0.0.1', port)
@@ -619,8 +623,14 @@ s:settimeout(100500)
 rch, wch = fiber.channel(1), fiber.channel(1)
 sc = socket.connect(host, port)
 test_run:cmd("setopt delimiter ';'")
+socket_opened = true
 cfiber = fiber.create(function(sc, rch, wch)
-    while sc:send(wch:get()) and rch:put(sc:receive("*l")) do end
+    while socket_opened do
+        sc:send(wch:get())
+        local data = sc:receive("*l")
+        if not socket_opened then sc:close() end
+        rch:put(data)
+    end
 end, sc, rch, wch);
 test_run:cmd("setopt delimiter ''");
 
@@ -651,9 +661,9 @@ rch:get()
 wch:put("DATA\n")
 c:receive(4)
 c:receive("*l")
+socket_opened = false
 wch:put("Fu")
 c:send("354 Please type your message\n")
-sc:close()
 c:receive("*l", "Line: ")
 c:receive()
 c:receive(10)
@@ -960,18 +970,30 @@ server:close()
 
 test_run:cmd("clear filter")
 
--- case: sicket receive inconsistent behavior
+-- case: socket receive inconsistent behavior
 chan = fiber.channel()
 counter = 0
 fn = function(s) counter = 0; while true do s:write((tostring(counter)):rep(chan:get())); counter = counter + 1 end end
-srv = socket.tcp_server('0.0.0.0', 8888, fn)
-s = socket.connect('localhost', 8888)
-chan:put(5)
-chan:put(5)
-s:receive(5)
-chan:put(5)
-s:settimeout(1)
-s:receive('*a')
-s:close()
-srv:close()
+srv = nil
+test_run:cmd("setopt delimiter ';'")
+test_run:wait_cond(function()
+    port = 32768 + math.random(0, 32767)
+    srv = socket.tcp_server('0.0.0.0', port, fn)
+    return srv ~= nil
+end, 100);
+receive1 = nil; receive2 = nil;
+if srv ~= nil then
+    s = socket.connect('localhost', port)
+    chan:put(5)
+    chan:put(5)
+    receive1 = s:receive(5)
+    chan:put(5)
+    s:settimeout(1)
+    receive2 = s:receive('*a')
+    s:close()
+    srv:close()
+end;
+test_run:cmd("setopt delimiter ''");
+receive1
+receive2
 
diff --git a/test/app/suite.ini b/test/app/suite.ini
index 79432e29a7..dd802d98cf 100644
--- a/test/app/suite.ini
+++ b/test/app/suite.ini
@@ -7,4 +7,3 @@ use_unix_sockets = True
 use_unix_sockets_iproto = True
 is_parallel = True
 pretest_clean = True
-fragile = socket.test.lua ; gh-4426 gh-4451
-- 
2.17.1

^ permalink raw reply	[flat|nested] 9+ messages in thread
* [Tarantool-patches] [PATCH] test: fix flaky socket test
@ 2019-12-04 13:43 Ilya Kosarev
  2019-12-05 21:31 ` Vladislav Shpilevoy
  0 siblings, 1 reply; 9+ messages in thread
From: Ilya Kosarev @ 2019-12-04 13:43 UTC (permalink / raw)
  To: tarantool-patches; +Cc: v.shpilevoy

socket.test had a number of flaky problems:
- socket readableness expectation
- race conditions on socket shutdown in emulation test cases
- tcp_server stability in socket receive inconsistent behavior case
Now they are solved. Port randomization is improved.
Socket test is not fragile anymore.

Closes #4451, #4426, #4469
---
Branch: https://github.com/tarantool/tarantool/tree/i.kosarev/gh-4426-4451-fix-socket-test
Issues: https://github.com/tarantool/tarantool/issues/4426
        https://github.com/tarantool/tarantool/issues/4451
        https://github.com/tarantool/tarantool/issues/4469

 test/app/socket.result   | 84 +++++++++++++++++++++++++---------------
 test/app/socket.test.lua | 60 +++++++++++++++++++---------
 test/app/suite.ini       |  1 -
 3 files changed, 94 insertions(+), 51 deletions(-)

diff --git a/test/app/socket.result b/test/app/socket.result
index fd299424c9..42dde8f375 100644
--- a/test/app/socket.result
+++ b/test/app/socket.result
@@ -45,6 +45,9 @@ test_run:cmd("push filter '(error: .builtin/.*[.]lua):[0-9]+' to '\\1'")
 WAIT_COND_TIME = 10
 ---
 ...
+WAIT_TCP_CONNECT_TIME = 240
+---
+...
 socket('PF_INET', 'SOCK_STREAM', 'tcp121222');
 ---
 - null
@@ -107,7 +110,7 @@ s:nonblock(true)
 ---
 - true
 ...
-s:readable(.1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -227,7 +230,7 @@ s:syswrite(ffi.cast('const char *', ping), #ping)
 ---
 - 6
 ...
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -830,7 +833,7 @@ sc:sendto('127.0.0.1', s:name().port, 'Hello, world')
 ---
 - 12
 ...
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -842,7 +845,7 @@ sc:sendto('127.0.0.1', s:name().port, 'Hello, world, 2')
 ---
 - 15
 ...
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -898,7 +901,7 @@ sc:sendto('127.0.0.1', s:name().port, 'Hello, World!')
 ---
 - 13
 ...
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 ---
 - true
 ...
@@ -1074,6 +1077,15 @@ master:setsockopt('SOL_SOCKET', 'SO_REUSEADDR', true)
 ---
 - true
 ...
+seed = ''
+---
+...
+for d in string.gmatch(box.info.uuid, '%d') do  seed = seed .. d end
+---
+...
+math.randomseed(tonumber(seed))
+---
+...
 port = 32768 + math.random(0, 32767)
 ---
 ...
@@ -1092,7 +1104,7 @@ test_run:wait_cond(function()
         return false, master:error()
     end
     return true
-end, WAIT_COND_TIME);
+end, 100);
 ---
 - true
 ...
@@ -1822,8 +1834,14 @@ test_run:cmd("setopt delimiter ';'")
 ---
 - true
 ...
+socket_opened = true
 cfiber = fiber.create(function(sc, rch, wch)
-    while sc:send(wch:get()) and rch:put(sc:receive("*l")) do end
+    while socket_opened do
+        sc:send(wch:get())
+        local data = sc:receive("*l")
+        if not socket_opened then sc:close() end
+        rch:put(data)
+    end
 end, sc, rch, wch);
 ---
 ...
@@ -1936,6 +1954,9 @@ c:receive("*l")
 ---
 - 
 ...
+socket_opened = false
+---
+...
 wch:put("Fu")
 ---
 - true
@@ -1944,10 +1965,6 @@ c:send("354 Please type your message\n")
 ---
 - 29
 ...
-sc:close()
----
-- 1
-...
 c:receive("*l", "Line: ")
 ---
 - null
@@ -2816,7 +2833,7 @@ test_run:cmd("clear filter")
 ---
 - true
 ...
--- case: sicket receive inconsistent behavior
+-- case: socket receive inconsistent behavior
 chan = fiber.channel()
 ---
 ...
@@ -2826,41 +2843,46 @@ counter = 0
 fn = function(s) counter = 0; while true do s:write((tostring(counter)):rep(chan:get())); counter = counter + 1 end end
 ---
 ...
-srv = socket.tcp_server('0.0.0.0', 8888, fn)
+srv = nil
 ---
 ...
-s = socket.connect('localhost', 8888)
+test_run:cmd("setopt delimiter ';'")
 ---
+- true
 ...
-chan:put(5)
+test_run:wait_cond(function()
+    port = 32768 + math.random(0, 32767)
+    srv = socket.tcp_server('0.0.0.0', port, fn)
+    return srv ~= nil
+end, 100);
 ---
 - true
 ...
-chan:put(5)
+receive1 = nil; receive2 = nil;
 ---
-- true
 ...
-s:receive(5)
+if srv ~= nil then
+    s = socket.connect('localhost', port)
+    chan:put(5)
+    chan:put(5)
+    receive1 = s:receive(5)
+    chan:put(5)
+    s:settimeout(1)
+    receive2 = s:receive('*a')
+    s:close()
+    srv:close()
+end;
 ---
-- '00000'
 ...
-chan:put(5)
+test_run:cmd("setopt delimiter ''");
 ---
 - true
 ...
-s:settimeout(1)
+receive1
 ---
-- 1
+- '00000'
 ...
-s:receive('*a')
+receive2
 ---
 - '1111122222'
 ...
-s:close()
----
-- 1
-...
-srv:close()
----
-- true
-...
diff --git a/test/app/socket.test.lua b/test/app/socket.test.lua
index c72d41763f..64f1e07471 100644
--- a/test/app/socket.test.lua
+++ b/test/app/socket.test.lua
@@ -14,6 +14,7 @@ test_run = env.new()
 test_run:cmd("push filter '(error: .builtin/.*[.]lua):[0-9]+' to '\\1'")
 
 WAIT_COND_TIME = 10
+WAIT_TCP_CONNECT_TIME = 240
 
 socket('PF_INET', 'SOCK_STREAM', 'tcp121222');
 
@@ -39,7 +40,7 @@ s:nonblock(false)
 s:nonblock()
 s:nonblock(true)
 
-s:readable(.1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 s:wait(.1)
 socket.iowait(s:fd(), 'RW')
 socket.iowait(s:fd(), 3)
@@ -75,7 +76,7 @@ ping = msgpack.encode(string.len(ping)) .. ping
 
 -- test syswrite with char *
 s:syswrite(ffi.cast('const char *', ping), #ping)
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 s:wait(.01)
 
 pong = s:sysread()
@@ -266,11 +267,11 @@ s = socket('AF_INET', 'SOCK_DGRAM', 'udp')
 s:bind('127.0.0.1', 0)
 sc = socket('AF_INET', 'SOCK_DGRAM', 'udp')
 sc:sendto('127.0.0.1', s:name().port, 'Hello, world')
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 s:recv()
 
 sc:sendto('127.0.0.1', s:name().port, 'Hello, world, 2')
-s:readable(10)
+s:readable(WAIT_TCP_CONNECT_TIME)
 d, from = s:recvfrom()
 from.port > 0
 from.port = 'Random port'
@@ -286,7 +287,7 @@ sc = socket('AF_INET', 'SOCK_DGRAM', 'udp')
 sc:nonblock(true)
 sc:sendto('127.0.0.1', s:name().port)
 sc:sendto('127.0.0.1', s:name().port, 'Hello, World!')
-s:readable(1)
+s:readable(WAIT_TCP_CONNECT_TIME)
 data, from = s:recvfrom(10)
 data
 s:sendto(from.host, from.port, 'Hello, hello!')
@@ -343,6 +344,9 @@ s = nil
 -- random port
 master = socket('PF_INET', 'SOCK_STREAM', 'tcp')
 master:setsockopt('SOL_SOCKET', 'SO_REUSEADDR', true)
+seed = ''
+for d in string.gmatch(box.info.uuid, '%d') do  seed = seed .. d end
+math.randomseed(tonumber(seed))
 port = 32768 + math.random(0, 32767)
 -- SO_REUSEADDR allows to bind to the same source addr:port twice,
 -- so listen() can return EADDRINUSE and so we check it within
@@ -356,7 +360,7 @@ test_run:wait_cond(function()
         return false, master:error()
     end
     return true
-end, WAIT_COND_TIME);
+end, 100);
 function gh361()
     local s = socket('PF_INET', 'SOCK_STREAM', 'tcp')
     s:sysconnect('127.0.0.1', port)
@@ -619,8 +623,14 @@ s:settimeout(100500)
 rch, wch = fiber.channel(1), fiber.channel(1)
 sc = socket.connect(host, port)
 test_run:cmd("setopt delimiter ';'")
+socket_opened = true
 cfiber = fiber.create(function(sc, rch, wch)
-    while sc:send(wch:get()) and rch:put(sc:receive("*l")) do end
+    while socket_opened do
+        sc:send(wch:get())
+        local data = sc:receive("*l")
+        if not socket_opened then sc:close() end
+        rch:put(data)
+    end
 end, sc, rch, wch);
 test_run:cmd("setopt delimiter ''");
 
@@ -651,9 +661,9 @@ rch:get()
 wch:put("DATA\n")
 c:receive(4)
 c:receive("*l")
+socket_opened = false
 wch:put("Fu")
 c:send("354 Please type your message\n")
-sc:close()
 c:receive("*l", "Line: ")
 c:receive()
 c:receive(10)
@@ -960,18 +970,30 @@ server:close()
 
 test_run:cmd("clear filter")
 
--- case: sicket receive inconsistent behavior
+-- case: socket receive inconsistent behavior
 chan = fiber.channel()
 counter = 0
 fn = function(s) counter = 0; while true do s:write((tostring(counter)):rep(chan:get())); counter = counter + 1 end end
-srv = socket.tcp_server('0.0.0.0', 8888, fn)
-s = socket.connect('localhost', 8888)
-chan:put(5)
-chan:put(5)
-s:receive(5)
-chan:put(5)
-s:settimeout(1)
-s:receive('*a')
-s:close()
-srv:close()
+srv = nil
+test_run:cmd("setopt delimiter ';'")
+test_run:wait_cond(function()
+    port = 32768 + math.random(0, 32767)
+    srv = socket.tcp_server('0.0.0.0', port, fn)
+    return srv ~= nil
+end, 100);
+receive1 = nil; receive2 = nil;
+if srv ~= nil then
+    s = socket.connect('localhost', port)
+    chan:put(5)
+    chan:put(5)
+    receive1 = s:receive(5)
+    chan:put(5)
+    s:settimeout(1)
+    receive2 = s:receive('*a')
+    s:close()
+    srv:close()
+end;
+test_run:cmd("setopt delimiter ''");
+receive1
+receive2
 
diff --git a/test/app/suite.ini b/test/app/suite.ini
index 79432e29a7..dd802d98cf 100644
--- a/test/app/suite.ini
+++ b/test/app/suite.ini
@@ -7,4 +7,3 @@ use_unix_sockets = True
 use_unix_sockets_iproto = True
 is_parallel = True
 pretest_clean = True
-fragile = socket.test.lua ; gh-4426 gh-4451
-- 
2.17.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-12-17  0:03 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-30 15:28 [tarantool-patches] [PATCH] test: fix flaky socket test Ilya Kosarev
2019-11-26  1:19 [Tarantool-patches] " Ilya Kosarev
2019-11-26 21:45 Ilya Kosarev
2019-12-04 13:43 Ilya Kosarev
2019-12-05 21:31 ` Vladislav Shpilevoy
2019-12-06 16:01   ` Ilya Kosarev
2019-12-08 15:52     ` Vladislav Shpilevoy
2019-12-10 14:36       ` Ilya Kosarev
2019-12-17  0:03         ` Vladislav Shpilevoy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox