about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2023-05-14 22:28:31 +0200
committerRobert Hensing <robert@roberthensing.nl>2023-06-13 10:17:02 +0200
commit18c7f6237f92ef5ef9d7cf106ec2ffb72af336fc (patch)
treecfa1110a901732a7b19d19c59a230858418959f6 /lib
parent3a86958c974bc3a03c32ab33ecfc0ec9498c7869 (diff)
downloadnixlib-18c7f6237f92ef5ef9d7cf106ec2ffb72af336fc.tar
nixlib-18c7f6237f92ef5ef9d7cf106ec2ffb72af336fc.tar.gz
nixlib-18c7f6237f92ef5ef9d7cf106ec2ffb72af336fc.tar.bz2
nixlib-18c7f6237f92ef5ef9d7cf106ec2ffb72af336fc.tar.lz
nixlib-18c7f6237f92ef5ef9d7cf106ec2ffb72af336fc.tar.xz
nixlib-18c7f6237f92ef5ef9d7cf106ec2ffb72af336fc.tar.zst
nixlib-18c7f6237f92ef5ef9d7cf106ec2ffb72af336fc.zip
lib.systems.{equals,toLosslessStringMaybe}: init
Diffstat (limited to 'lib')
-rw-r--r--lib/systems/default.nix33
-rw-r--r--lib/tests/systems.nix61
2 files changed, 86 insertions, 8 deletions
diff --git a/lib/systems/default.nix b/lib/systems/default.nix
index f4784c61c675..abaad19a3e1d 100644
--- a/lib/systems/default.nix
+++ b/lib/systems/default.nix
@@ -9,6 +9,39 @@ rec {
   examples = import ./examples.nix { inherit lib; };
   architectures = import ./architectures.nix { inherit lib; };
 
+  /*
+    Elaborated systems contain functions, which means that they don't satisfy
+    `==` for a lack of reflexivity.
+
+    They might *appear* to satisfy `==` reflexivity when the same exact value is
+    compared to itself, because object identity is used as an "optimization";
+    compare the value with a reconstruction of itself, e.g. with `f == a: f a`,
+    or perhaps calling `elaborate` twice, and one will see reflexivity fail as described.
+
+    Hence a custom equality test.
+
+    Note that this does not canonicalize the systems, so you'll want to make sure
+    both arguments have been `elaborate`-d.
+  */
+  equals =
+    let uncomparable = { canExecute = null; emulator = null; emulatorAvailable = null; isCompatible = null; };
+    in a: b: a // uncomparable == b // uncomparable;
+
+  /*
+    Try to convert an elaborated system back to a simple string. If not possible,
+    return null. So we have the property:
+
+        sys: _valid_ sys ->
+          sys == elaborate (toLosslessStringMaybe sys)
+
+    NOTE: This property is not guaranteed when `sys` was elaborated by a different
+          version of Nixpkgs.
+  */
+  toLosslessStringMaybe = sys:
+    if lib.isString sys then sys
+    else if equals sys (elaborate sys.system) then sys.system
+    else null;
+
   /* List of all Nix system doubles the nixpkgs flake will expose the package set
      for. All systems listed here must be supported by nixpkgs as `localSystem`.
 
diff --git a/lib/tests/systems.nix b/lib/tests/systems.nix
index 2afe128c4208..082b3549086f 100644
--- a/lib/tests/systems.nix
+++ b/lib/tests/systems.nix
@@ -1,10 +1,6 @@
-# We assert that the new algorithmic way of generating these lists matches the
-# way they were hard-coded before.
-#
-# One might think "if we exhaustively test, what's the point of procedurally
-# calculating the lists anyway?". The answer is one can mindlessly update these
-# tests as new platforms become supported, and then just give the diff a quick
-# sanity check before committing :).
+# Run:
+# [nixpkgs]$ nix-instantiate --eval --strict lib/tests/systems.nix
+# Expected output: [], or the failed cases
 let
   lib = import ../default.nix;
   mseteq = x: y: {
@@ -12,7 +8,16 @@ let
     expected = lib.sort lib.lessThan y;
   };
 in
-with lib.systems.doubles; lib.runTests {
+lib.runTests (
+# We assert that the new algorithmic way of generating these lists matches the
+# way they were hard-coded before.
+#
+# One might think "if we exhaustively test, what's the point of procedurally
+# calculating the lists anyway?". The answer is one can mindlessly update these
+# tests as new platforms become supported, and then just give the diff a quick
+# sanity check before committing :).
+
+(with lib.systems.doubles; {
   testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ mmix ++ js ++ genode ++ redox);
 
   testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv6l-netbsd" "armv6l-none" "armv7a-linux" "armv7a-netbsd" "armv7l-linux" "armv7l-netbsd" "arm-none" "armv7a-darwin" ];
@@ -39,4 +44,44 @@ with lib.systems.doubles; lib.runTests {
   testopenbsd = mseteq openbsd [ "i686-openbsd" "x86_64-openbsd" ];
   testwindows = mseteq windows [ "i686-cygwin" "x86_64-cygwin" "i686-windows" "x86_64-windows" ];
   testunix = mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ cygwin ++ redox);
+})
+
+// {
+  test_equals_example_x86_64-linux = {
+    expr = lib.systems.equals (lib.systems.elaborate "x86_64-linux") (lib.systems.elaborate "x86_64-linux");
+    expected = true;
+  };
+
+  test_toLosslessStringMaybe_example_x86_64-linux = {
+    expr = lib.systems.toLosslessStringMaybe (lib.systems.elaborate "x86_64-linux");
+    expected = "x86_64-linux";
+  };
+  test_toLosslessStringMaybe_fail = {
+    expr = lib.systems.toLosslessStringMaybe (lib.systems.elaborate "x86_64-linux" // { something = "extra"; });
+    expected = null;
+  };
 }
+
+# Generate test cases to assert that a change in any non-function attribute makes a platform unequal
+// lib.concatMapAttrs (platformAttrName: origValue: {
+
+  ${"test_equals_unequal_${platformAttrName}"} =
+    let modified =
+          assert origValue != arbitraryValue;
+          lib.systems.elaborate "x86_64-linux" // { ${platformAttrName} = arbitraryValue; };
+        arbitraryValue = "<<modified>>";
+    in {
+      expr = lib.systems.equals (lib.systems.elaborate "x86_64-linux") modified;
+      expected = {
+        # Changes in these attrs are not detectable because they're function.
+        # The functions should be derived from the data, so this is not a problem.
+        canExecute = null;
+        emulator = null;
+        emulatorAvailable = null;
+        isCompatible = null;
+      }?${platformAttrName};
+    };
+
+}) (lib.systems.elaborate "x86_64-linux" /* arbitrary choice, just to get all the elaborated attrNames */)
+
+)