| 
									
										
										
										
											2017-07-28 20:05:35 -04:00
										 |  |  | { lib }: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | let | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:36 +00:00
										 |  |  | inherit (builtins) trace attrNamesToStr isAttrs isFunction isList isInt | 
					
						
							|  |  |  |         isString isBool head substring attrNames; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:38 +00:00
										 |  |  | inherit (lib) all id mapAttrsFlatten elem; | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | in | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | rec { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-04 17:53:56 +02:00
										 |  |  |   inherit (builtins) addErrorContext; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   addErrorContextToAttrs = lib.mapAttrs (a: v: lib.addErrorContext "while evaluating ${a}" v); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 15:48:54 +00:00
										 |  |  |   traceIf = p: msg: x: if p then trace msg x else x; | 
					
						
							| 
									
										
										
										
											2014-10-04 17:53:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 15:48:54 +00:00
										 |  |  |   traceVal = x: trace x x; | 
					
						
							|  |  |  |   traceXMLVal = x: trace (builtins.toXML x) x; | 
					
						
							|  |  |  |   traceXMLValMarked = str: x: trace (str + builtins.toXML x) x; | 
					
						
							| 
									
										
										
										
											2009-02-09 16:51:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-26 01:28:06 +02:00
										 |  |  |   # strict trace functions (traced structure is fully evaluated and printed) | 
					
						
							| 
									
										
										
										
											2017-06-06 22:42:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* `builtins.trace`, but the value is `builtins.deepSeq`ed first. */ | 
					
						
							| 
									
										
										
										
											2016-06-26 01:28:06 +02:00
										 |  |  |   traceSeq = x: y: trace (builtins.deepSeq x x) y; | 
					
						
							| 
									
										
										
										
											2017-06-06 22:42:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Like `traceSeq`, but only down to depth n.
 | 
					
						
							|  |  |  |    * This is very useful because lots of `traceSeq` usages | 
					
						
							|  |  |  |    * lead to an infinite recursion. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   traceSeqN = depth: x: y: with lib; | 
					
						
							|  |  |  |     let snip = v: if      isList  v then noQuotes "[…]" v | 
					
						
							|  |  |  |                   else if isAttrs v then noQuotes "{…}" v | 
					
						
							|  |  |  |                   else v; | 
					
						
							|  |  |  |         noQuotes = str: v: { __pretty = const str; val = v; }; | 
					
						
							|  |  |  |         modify = n: fn: v: if (n == 0) then fn v | 
					
						
							|  |  |  |                       else if isList  v then map (modify (n - 1) fn) v | 
					
						
							|  |  |  |                       else if isAttrs v then mapAttrs | 
					
						
							|  |  |  |                         (const (modify (n - 1) fn)) v | 
					
						
							|  |  |  |                       else v; | 
					
						
							|  |  |  |     in trace (generators.toPretty { allowPrettyValues = true; } | 
					
						
							|  |  |  |                (modify depth snip x)) y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* `traceSeq`, but the same value is traced and returned */ | 
					
						
							| 
									
										
										
										
											2016-06-26 01:28:06 +02:00
										 |  |  |   traceValSeq = v: traceVal (builtins.deepSeq v v); | 
					
						
							| 
									
										
										
										
											2017-06-06 22:42:30 +02:00
										 |  |  |   /* `traceValSeq` but with fixed depth */ | 
					
						
							|  |  |  |   traceValSeqN = depth: v: traceSeqN depth v v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-26 01:28:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:35 +00:00
										 |  |  |   # this can help debug your code as well - designed to not produce thousands of lines | 
					
						
							| 
									
										
										
										
											2017-03-11 17:39:40 -05:00
										 |  |  |   traceShowVal = x: trace (showVal x) x; | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:46 +00:00
										 |  |  |   traceShowValMarked = str: x: trace (str + showVal x) x; | 
					
						
							| 
									
										
										
										
											2017-03-11 17:39:40 -05:00
										 |  |  |   attrNamesToStr = a: lib.concatStringsSep "; " (map (x: "${x}=") (attrNames a)); | 
					
						
							|  |  |  |   showVal = x: | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:46 +00:00
										 |  |  |       if isAttrs x then | 
					
						
							| 
									
										
										
										
											2009-03-25 13:48:55 +00:00
										 |  |  |           if x ? outPath then "x is a derivation, name ${if x ? name then x.name else "<no name>"}, { ${attrNamesToStr x} }" | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:35 +00:00
										 |  |  |           else "x is attr set { ${attrNamesToStr x} }" | 
					
						
							| 
									
										
										
										
											2009-05-24 10:57:46 +00:00
										 |  |  |       else if isFunction x then "x is a function" | 
					
						
							| 
									
										
										
										
											2009-03-25 13:48:55 +00:00
										 |  |  |       else if x == [] then "x is an empty list" | 
					
						
							| 
									
										
										
										
											2009-07-17 12:04:34 +00:00
										 |  |  |       else if isList x then "x is a list, first element is: ${showVal (head x)}" | 
					
						
							| 
									
										
										
										
											2009-03-25 13:48:55 +00:00
										 |  |  |       else if x == true then "x is boolean true" | 
					
						
							|  |  |  |       else if x == false then "x is boolean false" | 
					
						
							|  |  |  |       else if x == null then "x is null" | 
					
						
							| 
									
										
										
										
											2009-11-14 20:14:15 +00:00
										 |  |  |       else if isInt x then "x is an integer `${toString x}'" | 
					
						
							|  |  |  |       else if isString x then "x is a string `${substring 0 50 x}...'" | 
					
						
							| 
									
										
										
										
											2012-02-25 17:33:14 +00:00
										 |  |  |       else "x is probably a path `${substring 0 50 (toString x)}...'"; | 
					
						
							| 
									
										
										
										
											2009-11-14 20:14:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-04 17:53:56 +02:00
										 |  |  |   # trace the arguments passed to function and its result | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:36 +00:00
										 |  |  |   # maybe rewrite these functions in a traceCallXml like style. Then one function is enough | 
					
						
							| 
									
										
										
										
											2017-03-11 17:39:40 -05:00
										 |  |  |   traceCall  = n: f: a: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a)); | 
					
						
							|  |  |  |   traceCall2 = n: f: a: b: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b)); | 
					
						
							|  |  |  |   traceCall3 = n: f: a: b: c: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c)); | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 15:48:54 +00:00
										 |  |  |   # FIXME: rename this? | 
					
						
							| 
									
										
										
										
											2009-06-26 12:42:00 +00:00
										 |  |  |   traceValIfNot = c: x: | 
					
						
							|  |  |  |     if c x then true else trace (showVal x) false; | 
					
						
							| 
									
										
										
										
											2009-03-31 13:03:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Evaluate a set of tests.  A test is an attribute set {expr,
 | 
					
						
							|  |  |  |      expected}, denoting an expression and its expected result.  The | 
					
						
							|  |  |  |      result is a list of failed tests, each represented as {name, | 
					
						
							|  |  |  |      expected, actual}, denoting the attribute name of the failing | 
					
						
							|  |  |  |      test and its expected and actual results.  Used for regression | 
					
						
							|  |  |  |      testing of the functions in lib; see tests.nix for an example. | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:38 +00:00
										 |  |  |      Only tests having names starting with "test" are run. | 
					
						
							|  |  |  |      Add attr { tests = ["testName"]; } to run these test only | 
					
						
							| 
									
										
										
										
											2009-03-31 13:03:50 +00:00
										 |  |  |   */ | 
					
						
							|  |  |  |   runTests = tests: lib.concatLists (lib.attrValues (lib.mapAttrs (name: test: | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:38 +00:00
										 |  |  |     let testsToRun = if tests ? tests then tests.tests else []; | 
					
						
							|  |  |  |     in if (substring 0 4 name == "test" ||  elem name testsToRun) | 
					
						
							|  |  |  |        && ((testsToRun == []) || elem name tests.tests) | 
					
						
							| 
									
										
										
										
											2012-08-13 18:08:35 -04:00
										 |  |  |        && (test.expr != test.expected) | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-31 13:03:50 +00:00
										 |  |  |       then [ { inherit name; expected = test.expected; result = test.expr; } ] | 
					
						
							|  |  |  |       else [] ) tests)); | 
					
						
							| 
									
										
										
										
											2014-10-04 17:53:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:46 +00:00
										 |  |  |   # create a test assuming that list elements are true | 
					
						
							|  |  |  |   # usage: { testX = allTrue [ true ]; } | 
					
						
							| 
									
										
										
										
											2017-03-11 17:39:40 -05:00
										 |  |  |   testAllTrue = expr: { inherit expr; expected = map (x: true) expr; }; | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-26 01:23:25 +02:00
										 |  |  |   strict = v: | 
					
						
							|  |  |  |     trace "Warning: strict is deprecated and will be removed in the next release" | 
					
						
							|  |  |  |       (builtins.seq v v); | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   # example: (traceCallXml "myfun" id 3) will output something like | 
					
						
							|  |  |  |   # calling myfun arg 1: 3 result: 3 | 
					
						
							|  |  |  |   # this forces deep evaluation of all arguments and the result! | 
					
						
							|  |  |  |   # note: if result doesn't evaluate you'll get no trace at all (FIXME) | 
					
						
							|  |  |  |   #       args should be printed in any case | 
					
						
							|  |  |  |   traceCallXml = a: | 
					
						
							|  |  |  |     if !isInt a then | 
					
						
							|  |  |  |       traceCallXml 1 "calling ${a}\n" | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       let nr = a; | 
					
						
							|  |  |  |       in (str: expr: | 
					
						
							|  |  |  |           if isFunction expr then | 
					
						
							| 
									
										
										
										
											2014-10-04 17:53:56 +02:00
										 |  |  |             (arg: | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:36 +00:00
										 |  |  |               traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (strict arg)}" (expr arg) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2014-10-04 17:53:56 +02:00
										 |  |  |           else | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:36 +00:00
										 |  |  |             let r = strict expr; | 
					
						
							| 
									
										
										
										
											2015-03-19 15:48:54 +00:00
										 |  |  |             in trace "${str}\n result:\n${builtins.toXML r}" r | 
					
						
							| 
									
										
										
										
											2009-11-22 21:28:36 +00:00
										 |  |  |       ); | 
					
						
							| 
									
										
										
										
											2009-03-06 23:21:35 +00:00
										 |  |  | } |