[squeak-dev] Port numbers in network tests

Frank Shearar frank.shearar at gmail.com
Fri Apr 5 16:25:09 UTC 2013


On 5 April 2013 17:09, Chris Muller <asqueaker at gmail.com> wrote:
> 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.

Yes, but that's why Levente suggests asking the server for its port,
instead of relying on a common magic number.

frank

> 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