msg: { actual, expected ? { }, asString ? false, asJSON ? false , removeDunders ? false, safeToPrint ? true, throws ? false }: let preProcess = v: if removeDunders then undunder v else if asString then toString v else if asJSON then builtins.toJSON v else v; a = preProcess actual; e = preProcess expected; undunder = v: if builtins.isAttrs v then builtins.removeAttrs v [ "__toString" "__functor" ] else v; out = (if safeToPrint then builtins.toJSON (undunder (if throws then (builtins.tryEval actual).value else { inherit actual expected; })) else ''{"msg": "cannot be stringified ):"}''); success = if throws then (builtins.tryEval actual).success == false else (a == e); in { inherit success msg; } // (if success then { } else builtins.trace "FAILED ${msg}" { inherit actual expected; })