specify posix.deprecated:
- before:
    socket, getaddrinfo, close = posix.socket, posix.getaddrinfo, posix.close
    AF_INET, AF_INET6, AF_UNIX, AF_NETLINK =
      posix.AF_INET, posix.AF_INET6, posix.AF_UNIX, posix.AF_NETLINK
    SOCK_STREAM = posix.SOCK_STREAM

- describe connect:
  - before:
      connect, typeerrors = init (posix, "connect")

  - context with bad arguments: |
      badargs.diagnose (connect, "connect (int, table)")

      examples {
        ["it diagnoses wrong family types"] = function ()
          expect (connect (42, {family=false})).
            to_raise.any_of (typeerrors (2, "int", "family", "boolean"))
          expect (connect (42, {family=-1})).to_raise.any_of {
            "bad argument #2 to '?' (unsupported family type -1)",
            "bad argument #2 to 'connect' (unsupported family type -1)",
          }
        end
      }
      examples {
        ["it diagnoses wrong AF_INET field types"] = function ()
          expect (connect (42, {family=AF_INET, port=false})).
            to_raise.any_of (typeerrors (2, "int", "port", "boolean"))
          expect (connect (42, {family=AF_INET, port=9999, addr=false})).
            to_raise.any_of (typeerrors (2, "string", "addr", "boolean"))
        end
      }
      examples {
        ["it diagnoses invalid AF_INET fields"] = function ()
          expect (connect (42, {
            family=AF_INET, port=9999, addr="127.0.0.1", flags=false
          })).to_raise.any_of (typeerrors (2, nil, "flags"))
        end
      }
      examples {
        ["it diagnoses wrong AF_INET6 field types"] = function ()
          expect (connect (42, {family = AF_INET6, port = false})).
            to_raise.any_of (typeerrors (2, "int", "port", "boolean"))
          expect (connect (42, {family = AF_INET6, port = 9999, addr = false})).
            to_raise.any_of (typeerrors (2, "string", "addr", "boolean"))
        end
      }
      examples {
        ["it diagnoses invalid AF_INET6 fields"] = function ()
          expect (connect (42, {
            family=AF_INET6, port=9999, addr="::", flags=false
          })).to_raise.any_of (typeerrors (2, nil, "flags"))
        end
      }
      examples {
        ["it diagnoses wrong AF_UNIX field types"] = function ()
          expect (connect (42, {family = AF_UNIX, path = false})).
            to_raise.any_of (typeerrors (2, "string", "path", "boolean"))
        end
      }
      examples {
        ["it diagnoses invalid AF_UNIX fields"] = function ()
          expect (connect (42, {family=AF_UNIX, path="/tmp/afunix", port=9999})).
            to_raise.any_of (typeerrors (2, nil, "port"))
        end
      }
      if AF_NETLINK then
        examples {
          ["it diagnoses wrong AF_NETLINK field types"] = function ()
              expect (connect (42, {family = AF_NETLINK, pid = false})).
                to_raise.any_of (typeerrors (2, "int", "pid", "boolean"))
              expect (connect (42, {family = AF_NETLINK, pid = 9999, groups = false})).
                to_raise.any_of (typeerrors (2, "int", "groups", "boolean"))
          end
        }
        examples {
          ["it diagnoses invalid AF_NETLINK fields"] = function ()
            expect (connect (42, {family=AF_NETLINK, pid=9999, groups=9999, port=9999})).
              to_raise.any_of (typeerrors (2, nil, "port"))
          end
        }
      end

  - it returns true on success:
      fd = socket (AF_INET, SOCK_STREAM, 0)
      ait = getaddrinfo ("www.lua.org", "http", {family = AF_INET, socktype = SOCK_STREAM})
      expect (connect (fd, ait[1])).to_be (true)
      close (fd)



- describe bind:
  - before:
      bind, typeerrors = init (posix, "bind")

  - context with bad arguments: |
      badargs.diagnose (bind, "bind (int, table)")

      examples {
        ["it diagnoses wrong family types"] = function ()
          expect (bind (42, {family=false})).
            to_raise.any_of (typeerrors (2, "int", "family", "boolean"))
          expect (bind (42, {family=-1})).to_raise.any_of {
            "bad argument #2 to '?' (unsupported family type -1)",
            "bad argument #2 to 'bind' (unsupported family type -1)",
          }
        end
      }
      examples {
        ["it diagnoses wrong AF_INET field types"] = function ()
          expect (bind (42, {family=AF_INET, port=false})).
            to_raise.any_of (typeerrors (2, "int", "port", "boolean"))
          expect (bind (42, {family=AF_INET, port=9999, addr=false})).
            to_raise.any_of (typeerrors (2, "string", "addr", "boolean"))
        end
      }
      examples {
        ["it diagnoses invalid AF_INET fields"] = function ()
          expect (bind (42, {
            family=AF_INET, port=9999, addr="127.0.0.1", flags=false
          })).to_raise.any_of (typeerrors (2, nil, "flags"))
        end
      }
      examples {
        ["it diagnoses wrong AF_INET6 field types"] = function ()
          expect (bind (42, {family = AF_INET6, port = false})).
            to_raise.any_of (typeerrors (2, "int", "port", "boolean"))
          expect (bind (42, {family = AF_INET6, port = 9999, addr = false})).
            to_raise.any_of (typeerrors (2, "string", "addr", "boolean"))
        end
      }
      examples {
        ["it diagnoses invalid AF_INET6 fields"] = function ()
          expect (bind (42, {
            family=AF_INET6, port=9999, addr="::", flags=false
          })).to_raise.any_of (typeerrors (2, nil, "flags"))
        end
      }
      examples {
        ["it diagnoses wrong AF_UNIX field types"] = function ()
          expect (bind (42, {family = AF_UNIX, path = false})).
            to_raise.any_of (typeerrors (2, "string", "path", "boolean"))
        end
      }
      examples {
        ["it diagnoses invalid AF_UNIX fields"] = function ()
          expect (bind (42, {family=AF_UNIX, path="/tmp/afunix", port=9999})).
            to_raise.any_of (typeerrors (2, nil, "port"))
        end
      }
      if AF_NETLINK then
        examples {
          ["it diagnoses wrong AF_NETLINK field types"] = function ()
              expect (bind (42, {family = AF_NETLINK, pid = false})).
                to_raise.any_of (typeerrors (2, "int", "pid", "boolean"))
              expect (bind (42, {family = AF_NETLINK, pid = 9999, groups = false})).
                to_raise.any_of (typeerrors (2, "int", "groups", "boolean"))
          end
        }
        examples {
          ["it diagnoses invalid AF_NETLINK fields"] = function ()
            expect (bind (42, {family=AF_NETLINK, pid=9999, groups=9999, port=9999})).
              to_raise.any_of (typeerrors (2, nil, "port"))
          end
        }
      end

  - it returns true on success:
      fd = socket (AF_INET, SOCK_STREAM, 0)
      expect (bind (fd, {family = AF_INET, addr = "127.0.0.1", port = 13457 })).to_be (true)
      close (fd)


- describe exec:
  - before:
      exec, typeerrors = init (posix, "exec")

  # posix.exec takes a string or non-empty table as its second
  # argument, followed by zero or more strings only if the second
  # argument was a string; since we can't express that with
  # `badargs.diagnose` do it all manually again...
  - context with bad arguments:
    - 'it diagnoses argument #1 type not string':
        expect (exec (false)).to_raise.any_of (typeerrors (1, "string", "boolean"))
    - 'it diagnoses argument #2 type not table or string':
        expect (exec ("cmd", false)).
          to_raise.any_of (typeerrors (2, "?string|table", "boolean"))
    - 'it diagnoses argument #3 type not string':
        expect (exec ("cmd", "cmd", false)).
          to_raise.any_of (typeerrors (3, "string", "boolean"))
    - it diagnoses too many arguments:
        expect (exec ("cmd", {}, false)).to_raise.any_of (typeerrors (3))


- describe execp:
  - before:
      # redirect output to /dev/null
      dup2, fork, open, wait, O_WRONLY, O_APPEND =
        posix.dup2, posix.fork, posix.open, posix.wait, posix.O_WRONLY, posix.O_APPEND
      P_CHILD = 0

      function child (...)
        quietly = open ("/dev/null", bor (O_WRONLY, O_APPEND))
        dup2 (quietly, 1)
        execp (...)
        expect ("not reached").to_be (true)
      end

      execp, typeerrors = init (posix, "execp")

  # posix.execp takes a string or non-empty table as its second
  # argument, followed by zero or more strings only if the second
  # argument was a string; since we can't express that with
  # `badargs.diagnose` do it all manually again...
  - context with bad arguments:
    - 'it diagnoses argument #1 type not string':
        expect (execp (false)).to_raise.any_of (typeerrors (1, "string", "boolean"))
    - 'it diagnoses argument #2 type not table or string':
        expect (execp ("cmd", false)).
          to_raise.any_of (typeerrors (2, "?string|table", "boolean"))
    - 'it diagnoses argument #3 type not string':
        expect (execp ("cmd", "cmd", false)).
          to_raise.any_of (typeerrors (3, "string", "boolean"))
    - it diagnoses too many arguments:
        expect (execp ("cmd", {}, false)).to_raise.any_of (typeerrors (3))

  - it overwrites the running process with a shell invocation:
      process = fork ()
      if process == P_CHILD then
        child ("date", "+[%c]")
      else
        p, msg, ret = wait (process)
        expect (table.concat {msg, " ", tostring (ret)}).to_be "exited 0"
      end
  - it accepts a table of arguments:
      process = fork ()
      if process == P_CHILD then
        child ("date", {"+[%c]"})
      else
        p, msg, ret = wait (process)
        expect (table.concat {msg, " ", tostring (ret)}).to_be "exited 0"
      end
  - "it sets argv[0]":


- describe openlog:
  - before:
      openlog = posix.openlog

  - context with bad arguments: |
      if openlog then
        badargs.diagnose (openlog, "openlog (string, ?string, ?int)")

        examples {
          ["it diagnoses invalid options"] = function ()
            expect (openlog ("log", "cp*")).to_raise.any_of {
              "bad argument #2 to '?' (invalid openlog option '*')",
              "bad argument #2 to 'openlog' (invalid openlog option '*')",
            }
          end
        }
      end
