about summary refs log tree commit diff
path: root/tvix/boot/tests/default.nix
blob: a46341c08bcd5299323488baf2bb4b1dc8fa85e0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{ depot, pkgs, lib, ... }:

let
  # Seed a tvix-store with the tvix docs, then start a VM, ask it to list all
  # files in /nix/store, and ensure the store path is present, which acts as a
  # nice smoketest.
  mkBootTest =
    { blobServiceAddr ? "memory://"
    , directoryServiceAddr ? "memory://"
    , pathInfoServiceAddr ? "memory://"


      # The path to import.
    , path

      # Whether the path should be imported as a closure.
      # If false, importPathName must be specified.
    , isClosure ? false
    , importPathName ? null

      # The cmdline to pass to the VM.
      # Defaults to tvix.find, which lists all files in the store.
    , vmCmdline ? "tvix.find"
      # The string we expect to find in the VM output.
      # Defaults the value of `path` (the store path we upload).
    , assertVMOutput ? path
    }:

      assert isClosure -> importPathName == null;
      assert (!isClosure) -> importPathName != null;

      pkgs.stdenv.mkDerivation ({
        name = "run-vm";

        nativeBuildInputs = [
          depot.tvix.store
          depot.tvix.boot.runVM
        ];
        buildCommand = ''
          touch $out

          # Start the tvix daemon, listening on a unix socket.
          BLOB_SERVICE_ADDR=${blobServiceAddr} \
            DIRECTORY_SERVICE_ADDR=${directoryServiceAddr} \
            PATH_INFO_SERVICE_ADDR=${pathInfoServiceAddr} \
            tvix-store \
              --otlp=false \
              daemon -l $PWD/tvix-store.sock &

          # Wait for the socket to be created.
          while [ ! -e $PWD/tvix-store.sock ]; do sleep 1; done

          # Export env vars so that subsequent tvix-store commands will talk to
          # our tvix-store daemon over the unix socket.
          export BLOB_SERVICE_ADDR=grpc+unix://$PWD/tvix-store.sock
          export DIRECTORY_SERVICE_ADDR=grpc+unix://$PWD/tvix-store.sock
          export PATH_INFO_SERVICE_ADDR=grpc+unix://$PWD/tvix-store.sock
        '' + lib.optionalString (!isClosure) ''
          echo "Importing ${path} into tvix-store with name ${importPathName}…"
          cp -R ${path} ${importPathName}
          outpath=$(tvix-store import ${importPathName})

          echo "imported to $outpath"
        '' + lib.optionalString (isClosure) ''
          echo "Copying closure ${path}…"
          # This picks up the `closure` key in `$NIX_ATTRS_JSON_FILE` automatically.
          tvix-store --otlp=false copy
        '' + ''
          # Invoke a VM using tvix as the backing store, ensure the outpath appears in its listing.
          echo "Starting VM…"

          CH_CMDLINE="${vmCmdline}" run-tvix-vm 2>&1 | tee output.txt
          grep "${assertVMOutput}" output.txt
        '';
        requiredSystemFeatures = [ "kvm" ];
      } // lib.optionalAttrs (isClosure) {
        __structuredAttrs = true;
        exportReferencesGraph.closure = [ path ];
      });

  systemFor = sys: (depot.ops.nixos.nixosFor sys).system;

  testSystem = systemFor ({ modulesPath, pkgs, ... }: {
    # Set some options necessary to evaluate.
    boot.loader.systemd-boot.enable = true;
    # TODO: figure out how to disable this without causing eval to fail
    fileSystems."/" = {
      device = "/dev/root";
      fsType = "tmpfs";
    };

    services.getty.helpLine = "Onwards and upwards.";
    systemd.services.do-shutdown = {
      after = [ "getty.target" ];
      description = "Shut down again";
      wantedBy = [ "multi-user.target" ];
      serviceConfig.Type = "oneshot";
      script = "/run/current-system/sw/bin/systemctl poweroff --when=+10s";
    };

    # Don't warn about stateVersion.
    system.stateVersion = "24.05";
  });

in
depot.nix.readTree.drvTargets
{
  docs-memory = (mkBootTest {
    path = ../../docs;
    importPathName = "docs";
  });
  docs-persistent = (mkBootTest {
    blobServiceAddr = "objectstore+file://$PWD/blobs";
    directoryServiceAddr = "sled://$PWD/directories.sled";
    pathInfoServiceAddr = "sled://$PWD/pathinfo.sled";
    path = ../../docs;
    importPathName = "docs";
  });

  closure-tvix = (mkBootTest {
    blobServiceAddr = "objectstore+file://$PWD/blobs";
    path = depot.tvix.store;
    isClosure = true;
  });

  closure-nixos = (mkBootTest {
    blobServiceAddr = "objectstore+file://$PWD/blobs";
    path = testSystem;
    isClosure = true;
    vmCmdline = "init=${testSystem}/init panic=-1"; # reboot immediately on panic
    assertVMOutput = "Onwards and upwards.";
  });
}