[squeak-dev] Port numbers in network tests

Chris Muller asqueaker at gmail.com
Fri Apr 5 16:09:16 UTC 2013


Of course, the other half are the connecting clients.  Not sure how
your code works but in my network tests I've been bitten by ports in
use because the clients didn't know about the random port having been
selected.

On Fri, Apr 5, 2013 at 6:54 AM, Frank Shearar <frank.shearar at gmail.com> wrote:
> On 5 April 2013 10:04, Frank Shearar <frank.shearar at gmail.com> wrote:
>> On 5 April 2013 04:16, Levente Uzonyi <leves at elte.hu> wrote:
>>> On Thu, 4 Apr 2013, Frank Shearar wrote:
>>>
>>>> So this isn't exactly a common use case, except on build.squeak.org:
>>>>
>>>> You have a bunch of network tests, so in your #setUp you start up a
>>>> server on some port and in #tearDown you shut down the server. What
>>>> port do you use? Well, it doesn't really matter too much, as long as
>>>> the port's available. So you choose some probably-not-used port, like
>>>> 7799. (WebClient's test suite uses this.) All is almost always well,
>>>> because tests only fail when something's using 7799, which is almost
>>>> never.
>>>>
>>>> build.squeak.org has two executors, which means it can run two builds
>>>> concurrently. Suddenly, if you build SqueakTrunk, you'll trigger
>>>> ExternalPackages, ExternalPackages-Squeak4.3 and External-Squeak4.4.
>>>> Which means you will often execute the same test suite in different
>>>> images at the same time. Suddenly those tests using a hard-coded port
>>>> all fail, causing noise. (Xtreams' test suite is also vulnerable to
>>>> this problem: look at the  XTSocketReadingWritingTest failures in
>>>> http://build.squeak.org/job/ExternalPackages/43/testReport/)
>>>>
>>>> So what do we do?
>>>>
>>>> One approach that I can think of is, like WebClient's test suite, to
>>>> use a method #port returning the port to use in a test. However, #port
>>>> should not return a constant but rather attempt to open a port within
>>>> some range, and return _some_ open port. The problem here is a
>>>> time-of-check-time-of-use race.
>>>>
>>>> Now that might nearly always work. Can anyone think of a better method?
>>>
>>>
>>> The current socket implementation does exactly what you need. If a port is
>>> being used, the socket will listen on a random free port. So the solution is
>>> to ask the created Socket instance for which port it's listening on.
>>>
>>> Code showing the behavior:
>>>
>>> s := Socket newTCP.
>>> s listenOn: 1234 backlogSize: 10.
>>> s port.
>>> s2 := Socket newTCP.
>>> s2 listenOn: 1234 backlogSize: 10.
>>> { s port. s2 port } "==> #(1234 50542)"
>>
>> That's.... surprising. Is that something the SocketPlugin does? No EADDRINUSE?
>>
>> OK, so leaving aside that I think that's crazy behaviour,
>
> Upon reflection, it's not as crazy as I thought. listen() then
> actually means "try open this specific port. If you can't, open on
> some random port, and let me know I only got a listening socket on
> some random port, not the particular port I asked for, by returning
> EADDRINUSE."
>
> That's handy for protocols that dynamically instantiate servers (FTP, say).
>
> That _also_ means I've just been on a wild goose chase, thinking that
> concurrent builds on separate executors were interfering. Only those
> tests that expected a certain port number (and in WebClient that's
> just one test) would fail if another job had opened that port.
>
> frank
>


More information about the Squeak-dev mailing list