at 25.11-pre 4.5 kB view raw
1{ lib }: 2 3let 4 inherit (lib.strings) 5 concatStringsSep 6 ; 7 inherit (lib.lists) 8 filter 9 ; 10 inherit (lib.trivial) 11 showWarnings 12 ; 13in 14rec { 15 16 /** 17 Throw if pred is false, else return pred. 18 Intended to be used to augment asserts with helpful error messages. 19 20 # Inputs 21 22 `pred` 23 24 : Predicate that needs to succeed, otherwise `msg` is thrown 25 26 `msg` 27 28 : Message to throw in case `pred` fails 29 30 # Type 31 32 ``` 33 assertMsg :: Bool -> String -> Bool 34 ``` 35 36 # Examples 37 :::{.example} 38 ## `lib.asserts.assertMsg` usage example 39 40 ```nix 41 assertMsg false "nope" 42 stderr> error: nope 43 assert assertMsg ("foo" == "bar") "foo is not bar, silly"; "" 44 stderr> error: foo is not bar, silly 45 ``` 46 47 ::: 48 */ 49 # TODO(Profpatsch): add tests that check stderr 50 assertMsg = pred: msg: pred || builtins.throw msg; 51 52 /** 53 Specialized `assertMsg` for checking if `val` is one of the elements 54 of the list `xs`. Useful for checking enums. 55 56 # Inputs 57 58 `name` 59 60 : The name of the variable the user entered `val` into, for inclusion in the error message 61 62 `val` 63 64 : The value of what the user provided, to be compared against the values in `xs` 65 66 `xs` 67 68 : The list of valid values 69 70 # Type 71 72 ``` 73 assertOneOf :: String -> ComparableVal -> List ComparableVal -> Bool 74 ``` 75 76 # Examples 77 :::{.example} 78 ## `lib.asserts.assertOneOf` usage example 79 80 ```nix 81 let sslLibrary = "libressl"; 82 in assertOneOf "sslLibrary" sslLibrary [ "openssl" "bearssl" ] 83 stderr> error: sslLibrary must be one of [ 84 stderr> "openssl" 85 stderr> "bearssl" 86 stderr> ], but is: "libressl" 87 ``` 88 89 ::: 90 */ 91 assertOneOf = 92 name: val: xs: 93 assertMsg (lib.elem val xs) "${name} must be one of ${lib.generators.toPretty { } xs}, but is: ${ 94 lib.generators.toPretty { } val 95 }"; 96 97 /** 98 Specialized `assertMsg` for checking if every one of `vals` is one of the elements 99 of the list `xs`. Useful for checking lists of supported attributes. 100 101 # Inputs 102 103 `name` 104 105 : The name of the variable the user entered `val` into, for inclusion in the error message 106 107 `vals` 108 109 : The list of values of what the user provided, to be compared against the values in `xs` 110 111 `xs` 112 113 : The list of valid values 114 115 # Type 116 117 ``` 118 assertEachOneOf :: String -> List ComparableVal -> List ComparableVal -> Bool 119 ``` 120 121 # Examples 122 :::{.example} 123 ## `lib.asserts.assertEachOneOf` usage example 124 125 ```nix 126 let sslLibraries = [ "libressl" "bearssl" ]; 127 in assertEachOneOf "sslLibraries" sslLibraries [ "openssl" "bearssl" ] 128 stderr> error: each element in sslLibraries must be one of [ 129 stderr> "openssl" 130 stderr> "bearssl" 131 stderr> ], but is: [ 132 stderr> "libressl" 133 stderr> "bearssl" 134 stderr> ] 135 ``` 136 137 ::: 138 */ 139 assertEachOneOf = 140 name: vals: xs: 141 assertMsg (lib.all (val: lib.elem val xs) vals) 142 "each element in ${name} must be one of ${lib.generators.toPretty { } xs}, but is: ${ 143 lib.generators.toPretty { } vals 144 }"; 145 146 /** 147 Wrap a value with logic that throws an error when assertions 148 fail and emits any warnings. 149 150 # Inputs 151 152 `assertions` 153 154 : A list of assertions. If any of their `assertion` attrs is `false`, their `message` attrs will be emitted in a `throw`. 155 156 `warnings` 157 158 : A list of strings to emit as warnings. This function does no filtering on this list. 159 160 `val` 161 162 : A value to return, wrapped in `warn`, if a `throw` is not necessary. 163 164 # Type 165 166 ``` 167 checkAssertWarn :: [ { assertion :: Bool; message :: String } ] -> [ String ] -> Any -> Any 168 ``` 169 170 # Examples 171 :::{.example} 172 ## `lib.asserts.checkAssertWarn` usage example 173 ```nix 174 checkAssertWarn 175 [ { assertion = false; message = "Will fail"; } ] 176 [ ] 177 null 178 stderr> error: 179 stderr> Failed assertions: 180 stderr> - Will fail 181 182 checkAssertWarn 183 [ { assertion = true; message = "Will not fail"; } ] 184 [ "Will warn" ] 185 null 186 stderr> evaluation warning: Will warn 187 null 188 ``` 189 190 ::: 191 */ 192 checkAssertWarn = 193 assertions: warnings: val: 194 let 195 failedAssertions = map (x: x.message) (filter (x: !x.assertion) assertions); 196 in 197 if failedAssertions != [ ] then 198 throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}" 199 else 200 showWarnings warnings val; 201 202}