haskell-servant / servant

Main repository for the servant libraries — DSL for describing, serving, querying, mocking, documenting web applications and more!
https://docs.servant.dev/
1.8k stars 407 forks source link

servant-auth-client test fails on the 248th call to getIntClient on Mac #1693

Closed intolerable closed 1 year ago

intolerable commented 1 year ago

Running getIntClient repeatedly in the servant-auth-client test suite causes it to fail on the 248th call on Mac due to exhausting /dev/urandom:

Servant.Auth.Client
  The JWT combinator
    HasClient
      succeeds when the token does not have expiry [✔]
        +++ OK, passed 100 tests.
      fails when token is expired [✔]
        +++ OK, passed 100 tests.
      succeeds when the token is not expired [✘]

Failures:

  test/Servant/Auth/ClientSpec.hs:84:3: 
  1) Servant.Auth.Client, The JWT combinator, HasClient, succeeds when the token is not expired
       uncaught exception: IOException of type ResourceExhausted
       /dev/urandom: openFdAt: resource exhausted (Too many open files)
       (after 47 tests)

I suspect that this is an issue with an underlying library on Mac, rather than with servant-auth-server itself, but I don't know enough about the crypto libraries used in servant to make an educated guess.

Notably, this error isn't obvious if you run Servant.Auth.ClientSpec's tests in the order specified in the spec, since something (I'm not sure what) causes a different error to be reported from the "fails when token is expired" tests, so I'd recommend using hspec's --randomize option or moving the "fails when token is expired" test so it's executed first.

intolerable commented 1 year ago

updated to remove references to M2 because I'm getting the same behaviour on an Intel Mac

arianvp commented 1 year ago

This sounds like a file-descriptor leak.

intolerable commented 1 year ago

it's not a file descriptor leak per se, it's that the servant-auth-client and servant-auth-server test suites spin up a new server (with its own port) for every test case, and in Servant.Auth.ClientSpec that means we create a new server (with its own port and socket) for every QuickCheck example (lol)

switching around (which is per-test) for aroundAll (which is per-spec) solves this issue in a safe way