# Test whether `networking.proxy' work as expected.

# TODO: use a real proxy node and put this test into networking.nix
# TODO: test whether nix tools work as expected behind a proxy

let default-config = {
        imports = [ ./common/user-account.nix ];

        services.xserver.enable = false;

      };
in import ./make-test-python.nix ({ pkgs, ...} : {
  name = "networking-proxy";
  meta = with pkgs.lib.maintainers; {
    maintainers = [ ];
  };

  nodes = {
    # no proxy
    machine =
      { ... }:

      default-config;

    # proxy default
    machine2 =
      { ... }:

      default-config // {
        networking.proxy.default = "http://user:pass@host:port";
      };

    # specific proxy options
    machine3 =
      { ... }:

      default-config //
      {
        networking.proxy = {
          # useless because overridden by the next options
          default = "http://user:pass@host:port";
          # advanced proxy setup
          httpProxy = "123-http://user:pass@http-host:port";
          httpsProxy = "456-http://user:pass@https-host:port";
          rsyncProxy = "789-http://user:pass@rsync-host:port";
          ftpProxy = "101112-http://user:pass@ftp-host:port";
          noProxy = "131415-127.0.0.1,localhost,.localdomain";
        };
      };

    # mix default + proxy options
    machine4 =
      { ... }:

      default-config // {
        networking.proxy = {
          # open for all *_proxy env var
          default = "000-http://user:pass@default-host:port";
          # except for those 2
          rsyncProxy = "123-http://user:pass@http-host:port";
          noProxy = "131415-127.0.0.1,localhost,.localdomain";
        };
      };
    };

  testScript =
    ''
      from typing import Dict, Optional


      def get_machine_env(machine: Machine, user: Optional[str] = None) -> Dict[str, str]:
          """
          Gets the environment from a given machine, and returns it as a
          dictionary in the form:
              {"lowercase_var_name": "value"}

          Duplicate environment variables with the same name
          (e.g. "foo" and "FOO") are handled in an undefined manner.
          """
          if user is not None:
              env = machine.succeed("su - {} -c 'env -0'".format(user))
          else:
              env = machine.succeed("env -0")
          ret = {}
          for line in env.split("\0"):
              if "=" not in line:
                  continue

              key, val = line.split("=", 1)
              ret[key.lower()] = val
          return ret


      start_all()

      with subtest("no proxy"):
          assert "proxy" not in machine.succeed("env").lower()
          assert "proxy" not in machine.succeed("su - alice -c env").lower()

      with subtest("default proxy"):
          assert "proxy" in machine2.succeed("env").lower()
          assert "proxy" in machine2.succeed("su - alice -c env").lower()

      with subtest("explicitly-set proxy"):
          env = get_machine_env(machine3)
          assert "123" in env["http_proxy"]
          assert "456" in env["https_proxy"]
          assert "789" in env["rsync_proxy"]
          assert "101112" in env["ftp_proxy"]
          assert "131415" in env["no_proxy"]

          env = get_machine_env(machine3, "alice")
          assert "123" in env["http_proxy"]
          assert "456" in env["https_proxy"]
          assert "789" in env["rsync_proxy"]
          assert "101112" in env["ftp_proxy"]
          assert "131415" in env["no_proxy"]

      with subtest("default proxy + some other specifics"):
          env = get_machine_env(machine4)
          assert "000" in env["http_proxy"]
          assert "000" in env["https_proxy"]
          assert "123" in env["rsync_proxy"]
          assert "000" in env["ftp_proxy"]
          assert "131415" in env["no_proxy"]

          env = get_machine_env(machine4, "alice")
          assert "000" in env["http_proxy"]
          assert "000" in env["https_proxy"]
          assert "123" in env["rsync_proxy"]
          assert "000" in env["ftp_proxy"]
          assert "131415" in env["no_proxy"]
    '';
})
