• Kirill Smelkov's avatar
    golang: Deflake channel tests · 731f39e3
    Kirill Smelkov authored
    Channel tests are passing on an idle machine. However if there is
    another load - e.g. in the presence of simultaneous Firefox start,
    channel tests break, for example:
    
    	    def test_select():
    	        ...
    
    	        # non-blocking try recv: ok
    	        ch = chan()
    	        done = chan()
    	        def _():
    	            for i in range(N):
    	                ch.send(i)
    	            done.close()
    	        go(_)
    
    	        for i in range(N):
    	            tdelay()
    	            if i % 2:
    	                _, _rx = select(
    	                        ch.recv,
    	                        default,
    	                )
    	                assert (_, _rx) == (0, i)
    	            else:
    	                _, _rx = select(
    	                        ch.recv_,
    	                        default,
    	                )
    	>               assert (_, _rx) == (0, (i, True))
    	E               assert (1, None) == (0, (320, True))
    	E                 At index 0 diff: 1 != 0
    	E                 Use -v to get the full diff
    
    	golang_test.py:209: AssertionError
    
    The failure here is that it was default case selected, not ch.recv_. The
    default was selected because the sending goroutine was not fast to
    enqueue next send before we tried to receive. We were trying to make
    sure that the sender will be enqueued first via adding 1ms time delay
    before trying to receive, but in the presence of concurrent load spikes
    that turns out to be not enough.
    
    We could try to fix the test by increasing the time to sleep in tdelay,
    make the tests more slow and still not 100% reliable. However we can
    change the tests to instead actually wait for the condition that is
    semantically required: a sender enqueued on the channel.
    
    Do that everywhere where tdelay was used.
    
    Now tests are faster (it was ~3s total, now it is ~ 0.5s total) and pass
    irregardless of whether the machine is idle or otherwise loaded.
    731f39e3
golang_test.py 15 KB