141 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
let
 | 
						|
  user = "someuser";
 | 
						|
  password = "some_password";
 | 
						|
  port = builtins.toString 5232;
 | 
						|
 | 
						|
  common = { pkgs, ... }: {
 | 
						|
    services.radicale = {
 | 
						|
      enable = true;
 | 
						|
      config = ''
 | 
						|
        [auth]
 | 
						|
        type = htpasswd
 | 
						|
        htpasswd_filename = /etc/radicale/htpasswd
 | 
						|
        htpasswd_encryption = bcrypt
 | 
						|
 | 
						|
        [storage]
 | 
						|
        filesystem_folder = /tmp/collections
 | 
						|
      '';
 | 
						|
    };
 | 
						|
    # WARNING: DON'T DO THIS IN PRODUCTION!
 | 
						|
    # This puts unhashed secrets directly into the Nix store for ease of testing.
 | 
						|
    environment.etc."radicale/htpasswd".source = pkgs.runCommand "htpasswd" {} ''
 | 
						|
      ${pkgs.apacheHttpd}/bin/htpasswd -bcB "$out" ${user} ${password}
 | 
						|
    '';
 | 
						|
  };
 | 
						|
 | 
						|
in
 | 
						|
 | 
						|
  import ./make-test-python.nix ({ lib, ... }@args: {
 | 
						|
    name = "radicale";
 | 
						|
    meta.maintainers = with lib.maintainers; [ aneeshusa infinisil ];
 | 
						|
 | 
						|
    nodes = rec {
 | 
						|
      radicale = radicale1; # Make the test script read more nicely
 | 
						|
      radicale1 = lib.recursiveUpdate (common args) {
 | 
						|
        nixpkgs.overlays = [
 | 
						|
          (self: super: {
 | 
						|
            radicale1 = super.radicale1.overrideAttrs (oldAttrs: {
 | 
						|
              propagatedBuildInputs = with self.pythonPackages;
 | 
						|
                (oldAttrs.propagatedBuildInputs or []) ++ [ passlib ];
 | 
						|
            });
 | 
						|
          })
 | 
						|
        ];
 | 
						|
        system.stateVersion = "17.03";
 | 
						|
      };
 | 
						|
      radicale1_export = lib.recursiveUpdate radicale1 {
 | 
						|
        services.radicale.extraArgs = [
 | 
						|
          "--export-storage" "/tmp/collections-new"
 | 
						|
        ];
 | 
						|
        system.stateVersion = "17.03";
 | 
						|
      };
 | 
						|
      radicale2_verify = lib.recursiveUpdate radicale2 {
 | 
						|
        services.radicale.extraArgs = [ "--debug" "--verify-storage" ];
 | 
						|
        system.stateVersion = "17.09";
 | 
						|
      };
 | 
						|
      radicale2 = lib.recursiveUpdate (common args) {
 | 
						|
        system.stateVersion = "17.09";
 | 
						|
      };
 | 
						|
      radicale3 = lib.recursiveUpdate (common args) {
 | 
						|
        system.stateVersion = "20.09";
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    # This tests whether the web interface is accessible to an authenticated user
 | 
						|
    testScript = { nodes }: let
 | 
						|
      switchToConfig = nodeName: let
 | 
						|
        newSystem = nodes.${nodeName}.config.system.build.toplevel;
 | 
						|
      in "${newSystem}/bin/switch-to-configuration test";
 | 
						|
    in ''
 | 
						|
      with subtest("Check Radicale 1 functionality"):
 | 
						|
          radicale.succeed(
 | 
						|
              "${switchToConfig "radicale1"} >&2"
 | 
						|
          )
 | 
						|
          radicale.wait_for_unit("radicale.service")
 | 
						|
          radicale.wait_for_open_port(${port})
 | 
						|
          radicale.succeed(
 | 
						|
              "curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
 | 
						|
          )
 | 
						|
 | 
						|
      with subtest("Export data in Radicale 2 format"):
 | 
						|
          radicale.succeed("systemctl stop radicale")
 | 
						|
          radicale.succeed("ls -al /tmp/collections")
 | 
						|
          radicale.fail("ls -al /tmp/collections-new")
 | 
						|
 | 
						|
      with subtest("Radicale exits immediately after exporting storage"):
 | 
						|
          radicale.succeed(
 | 
						|
              "${switchToConfig "radicale1_export"} >&2"
 | 
						|
          )
 | 
						|
          radicale.wait_until_fails("systemctl status radicale")
 | 
						|
          radicale.succeed("ls -al /tmp/collections")
 | 
						|
          radicale.succeed("ls -al /tmp/collections-new")
 | 
						|
 | 
						|
      with subtest("Verify data in Radicale 2 format"):
 | 
						|
          radicale.succeed("rm -r /tmp/collections/${user}")
 | 
						|
          radicale.succeed("mv /tmp/collections-new/collection-root /tmp/collections")
 | 
						|
          radicale.succeed(
 | 
						|
              "${switchToConfig "radicale2_verify"} >&2"
 | 
						|
          )
 | 
						|
          radicale.wait_until_fails("systemctl status radicale")
 | 
						|
 | 
						|
          (retcode, logs) = radicale.execute("journalctl -u radicale -n 10")
 | 
						|
          assert (
 | 
						|
              retcode == 0 and "Verifying storage" in logs
 | 
						|
          ), "Radicale 2 didn't verify storage"
 | 
						|
          assert (
 | 
						|
              "failed" not in logs and "exception" not in logs
 | 
						|
          ), "storage verification failed"
 | 
						|
 | 
						|
      with subtest("Check Radicale 2 functionality"):
 | 
						|
          radicale.succeed(
 | 
						|
              "${switchToConfig "radicale2"} >&2"
 | 
						|
          )
 | 
						|
          radicale.wait_for_unit("radicale.service")
 | 
						|
          radicale.wait_for_open_port(${port})
 | 
						|
 | 
						|
          (retcode, output) = radicale.execute(
 | 
						|
              "curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
 | 
						|
          )
 | 
						|
          assert (
 | 
						|
              retcode == 0 and "VCALENDAR" in output
 | 
						|
          ), "Could not read calendar from Radicale 2"
 | 
						|
 | 
						|
          radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
 | 
						|
 | 
						|
      with subtest("Check Radicale 3 functionality"):
 | 
						|
          radicale.succeed(
 | 
						|
              "${switchToConfig "radicale3"} >&2"
 | 
						|
          )
 | 
						|
          radicale.wait_for_unit("radicale.service")
 | 
						|
          radicale.wait_for_open_port(${port})
 | 
						|
 | 
						|
          (retcode, output) = radicale.execute(
 | 
						|
              "curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
 | 
						|
          )
 | 
						|
          assert (
 | 
						|
              retcode == 0 and "VCALENDAR" in output
 | 
						|
          ), "Could not read calendar from Radicale 3"
 | 
						|
 | 
						|
          radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
 | 
						|
    '';
 | 
						|
})
 |