2 Collection of functions useful for debugging
3 broken nix expressions.
5 * `trace`-like functions take two values, print
6 the first to stderr and return the second.
7 * `traceVal`-like functions take one argument
8 which both printed and returned.
9 * `traceSeq`-like functions fully evaluate their
10 traced value before printing (not just to “weak
11 head normal form” like trace does by default).
12 * Functions that end in `-Fn` take an additional
13 function as their first argument, which is applied
14 to the traced value before it is printed.
38 Conditionally trace the supplied message, based on a predicate.
48 : Message that should be traced
57 traceIf :: bool -> string -> a -> a
62 ## `lib.debug.traceIf` usage example
65 traceIf true "hello" 3
74 if pred then trace msg x else x;
77 Trace the supplied value after applying a function to it, and
78 return the original value.
88 : Value to trace and return
93 traceValFn :: (a -> b) -> a -> a
98 ## `lib.debug.traceValFn` usage example
101 traceValFn (v: "mystring ${v}") "foo"
108 traceValFn = f: x: trace (f x) x;
111 Trace the supplied value and return it.
117 : Value to trace and return
127 ## `lib.debug.traceVal` usage example
137 traceVal = traceValFn id;
140 `builtins.trace`, but the value is `builtins.deepSeq`ed first.
150 : The value to return
155 traceSeq :: a -> b -> b
160 ## `lib.debug.traceSeq` usage example
163 trace { a.b.c = 3; } null
164 trace: { a = <CODE>; }
166 traceSeq { a.b.c = 3; } null
167 trace: { a = { b = { c = 3; }; }; }
173 traceSeq = x: y: trace (builtins.deepSeq x x) y;
176 Like `traceSeq`, but only evaluate down to depth n.
177 This is very useful because lots of `traceSeq` usages
178 lead to an infinite recursion.
184 : 1\. Function argument
188 : 2\. Function argument
192 : 3\. Function argument
197 traceSeqN :: Int -> a -> b -> b
202 ## `lib.debug.traceSeqN` usage example
205 traceSeqN 2 { a.b.c = 3; } null
206 trace: { a = { b = {…}; }; }
219 else if isAttrs v then
224 __pretty = const str;
231 else if isList v then
232 map (modify (n - 1) fn) v
233 else if isAttrs v then
234 mapAttrs (const (modify (n - 1) fn)) v
238 trace (generators.toPretty { allowPrettyValues = true; } (modify depth snip x)) y;
241 A combination of `traceVal` and `traceSeq` that applies a
242 provided function to the value to be traced after `deepSeq`ing
255 traceValSeqFn = f: v: traceValFn f (builtins.deepSeq v v);
258 A combination of `traceVal` and `traceSeq`.
266 traceValSeq = traceValSeqFn id;
269 A combination of `traceVal` and `traceSeqN` that applies a
270 provided function to the value to be traced.
280 : 2\. Function argument
288 traceSeqN depth (f v) v;
291 A combination of `traceVal` and `traceSeqN`.
297 : 1\. Function argument
303 traceValSeqN = traceValSeqNFn id;
306 Trace the input and output of a function `f` named `name`,
307 both down to `depth`.
309 This is useful for adding around a function call,
310 to see the before/after of values as they are transformed.
316 : 1\. Function argument
320 : 2\. Function argument
324 : 3\. Function argument
328 : 4\. Function argument
332 ## `lib.debug.traceFnSeqN` usage example
335 traceFnSeqN 2 "id" (x: x) { a.b.c = 3; }
336 trace: { fn = "id"; from = { a.b = {…}; }; to = { a.b = {…}; }; }
347 lib.traceSeqN (depth + 1) {
356 Evaluates a set of tests.
358 A test is an attribute set `{expr, expected}`,
359 denoting an expression and its expected result.
361 The result is a `list` of __failed tests__, each represented as
362 `{name, expected, result}`,
365 - What was passed as `expected`
367 - The actual `result` of the test
369 Used for regression testing of the functions in lib; see
370 tests.nix for more examples.
372 Important: Only attributes that start with `test` are executed.
374 - If you want to run only a subset of the tests add the attribute `tests = ["testName"];`
404 ## `lib.debug.runTests` usage example
409 expr = lib.and true false;
413 expr = lib.and true false;
420 name = "testAndFail";
436 testsToRun = if tests ? tests then tests.tests else [ ];
439 (substring 0 4 name == "test" || elem name testsToRun)
440 && ((testsToRun == [ ]) || elem name tests.tests)
441 && (test.expr != test.expected)
447 expected = test.expected;
458 Create a test assuming that list elements are `true`.
464 : 1\. Function argument
468 ## `lib.debug.testAllTrue` usage example
471 { testX = allTrue [ true ]; }
476 testAllTrue = expr: {
478 expected = map (x: true) expr;