pretty_assertions-1.4.0/.cargo_vcs_info.json0000644000000001570000000000100146420ustar { "git": { "sha1": "3f1ebc0cac5f88e875f036bf16636e15fa935c8d" }, "path_in_vcs": "pretty_assertions" }pretty_assertions-1.4.0/Cargo.lock0000644000000011010000000000100126030ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "diff" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "pretty_assertions" version = "1.4.0" dependencies = [ "diff", "yansi", ] [[package]] name = "yansi" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" pretty_assertions-1.4.0/Cargo.toml0000644000000023030000000000100126330ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "pretty_assertions" version = "1.4.0" authors = [ "Colin Kiegel ", "Florent Fayolle ", "Tom Milligan ", ] description = "Overwrite `assert_eq!` and `assert_ne!` with drop-in replacements, adding colorful diffs." documentation = "https://docs.rs/pretty_assertions" readme = "README.md" keywords = [ "assert", "diff", "pretty", "color", ] categories = ["development-tools"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-pretty-assertions/rust-pretty-assertions" [dependencies.diff] version = "0.1.12" [dependencies.yansi] version = "0.5" [features] alloc = [] default = ["std"] std = [] unstable = [] pretty_assertions-1.4.0/Cargo.toml.orig000064400000000000000000000016161046102023000163220ustar 00000000000000[package] name = "pretty_assertions" version = "1.4.0" authors = [ "Colin Kiegel ", "Florent Fayolle ", "Tom Milligan ", ] edition = "2018" description = "Overwrite `assert_eq!` and `assert_ne!` with drop-in replacements, adding colorful diffs." repository = "https://github.com/rust-pretty-assertions/rust-pretty-assertions" documentation = "https://docs.rs/pretty_assertions" license = "MIT OR Apache-2.0" categories = ["development-tools"] keywords = ["assert", "diff", "pretty", "color"] readme = "README.md" [features] default = ["std"] # Use the Rust standard library. # Exactly one of `std` and `alloc` is required. std = [] # Use the `alloc` crate. # Exactly one of `std` and `alloc` is required. alloc = [] # Enable unstable features. Requires nightly rustc. unstable = [] [dependencies] yansi = "0.5" diff = "0.1.12" pretty_assertions-1.4.0/LICENSE-APACHE000064400000000000000000000261361046102023000153630ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. pretty_assertions-1.4.0/LICENSE-MIT000064400000000000000000000021131046102023000150600ustar 00000000000000The MIT License (MIT) Copyright (c) 2016 rust-derive-builder contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pretty_assertions-1.4.0/README.md000064400000000000000000000102311046102023000147030ustar 00000000000000# Pretty Assertions [![Latest version](https://img.shields.io/crates/v/pretty-assertions.svg)](https://crates.io/crates/pretty-assertions) [![docs.rs](https://img.shields.io/docsrs/pretty_assertions)](https://docs.rs/pretty_assertions) [![Downloads of latest version](https://img.shields.io/crates/dv/pretty-assertions.svg)](https://crates.io/crates/pretty-assertions) [![All downloads](https://img.shields.io/crates/d/pretty-assertions.svg)](https://crates.io/crates/pretty-assertions) Overwrite `assert_eq!` with a drop-in replacement, adding a colorful diff. ## Usage When writing tests in Rust, you'll probably use `assert_eq!(a, b)` _a lot_. If such a test fails, it will present all the details of `a` and `b`. But you have to spot the differences yourself, which is not always straightforward, like here: ![standard assertion](https://raw.githubusercontent.com/rust-pretty-assertions/rust-pretty-assertions/2d2357ff56d22c51a86b2f1cfe6efcee9f5a8081/examples/standard_assertion.png) Wouldn't that task be _much_ easier with a colorful diff? ![pretty assertion](https://raw.githubusercontent.com/rust-pretty-assertions/rust-pretty-assertions/2d2357ff56d22c51a86b2f1cfe6efcee9f5a8081/examples/pretty_assertion.png) Yep — and you only need **one line of code** to make it happen: ```rust,ignore use pretty_assertions::{assert_eq, assert_ne}; ```
Show the example behind the screenshots above. ```rust,ignore // 1. add the `pretty_assertions` dependency to `Cargo.toml`. // 2. insert this line at the top of each module, as needed use pretty_assertions::{assert_eq, assert_ne}; fn main() { #[derive(Debug, PartialEq)] struct Foo { lorem: &'static str, ipsum: u32, dolor: Result, } let x = Some(Foo { lorem: "Hello World!", ipsum: 42, dolor: Ok("hey".to_string())}); let y = Some(Foo { lorem: "Hello Wrold!", ipsum: 42, dolor: Ok("hey ho!".to_string())}); assert_eq!(x, y); } ```
## Semantic Versioning The exact output of assertions is **not guaranteed** to be consistent over time, and may change between minor versions. The output of this crate is designed to be read by a human. It is not suitable for exact comparison, for example in snapshot testing. This crate adheres to semantic versioning for publically exported crate items, **except** the `private` module, which may change between any version. ## Tip Specify it as [`[dev-dependencies]`](http://doc.crates.io/specifying-dependencies.html#development-dependencies) and it will only be used for compiling tests, examples, and benchmarks. This way the compile time of `cargo build` won't be affected! Also add `#[cfg(test)]` to your `use` statements, like this: ```rust,ignore #[cfg(test)] use pretty_assertions::{assert_eq, assert_ne}; ``` ## Notes - Since `Rust 2018` edition, you need to declare `use pretty_assertions::{assert_eq, assert_ne};` per module. Before you would write `#[macro_use] extern crate pretty_assertions;`. - The replacement is only effective in your own crate, not in other libraries you include. - `assert_ne` is also switched to multi-line presentation, but does _not_ show a diff. - Under Windows, the terminal state is modified to properly handle VT100 escape sequences, which may break display for certain use cases. - The minimum supported rust version (MSRV) is 1.35.0 ### `no_std` support For `no_std` support, disable the `std` feature and enable the `alloc` feature: ```toml # Cargo.toml pretty_assertions = { version= "...", default-features = false, features = ["alloc"] } ``` ## License Licensed under either of - Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or ) - MIT license ([LICENSE-MIT](LICENSE-MIT) or ) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. ## Development - Cut a new release by creating a GitHub release with tag. Crate will be built and uploaded to crates.io by GHA. pretty_assertions-1.4.0/examples/pretty_assertion.png000064400000000000000000000516531046102023000214030ustar 00000000000000PNG  IHDR?sBIT|dtEXtSoftwaregnome-screenshot>*tEXtCreation TimeThu 04 Mar 2021 09:58:57 GMT_o} IDATxwxlv7e7N@^HzE/(ERZϫׂzU@lHХCH)dBHdC C3s3ywΔt׆ ƌ 6lÕٛ]n-pG`߾C|ݏO85ŵ^ɷ||[4 wٲo(++3p`:gaԵ$w3Ի;W]5^y{"ѣGfgo߶u4g|MՔ۷7!!A! :3ζwStߗfݯ_r-#\^ccټ;ϠA598>":\z 7sYKhԀg%5v%?6>>> :7y\g܇ȬGpi bh45Kq1:3X֨d2s1O8˜1SZZV,);W^1 fPQQkjZ/(ŗkٳ@ygs$6DocCnhw6:^{mGYtt$9=:Z&qƎVeı 2^ǎ{x7+ࢋbZشi+.|bzfM(++Q XXXF{Jys^v#s4h]G}}7XYSӷ7a!W~f-~i|={*%Dee?oۑhoC}UxIHERΤɏJᙧgҥKG&;2GSwwE}CBxxdzRXX{}GYslh#"œVԩfP,}ދ_;q"niz6ǧF0a 3}Ĉlڔݮ9kO}~KCǿ+LJFa\sP|/߶+o:i(?>[ 9y'#Vgr0l`Fi;f8ط_["#x @||,]w%/!-8V αMKY]JJʘػ,_MTT=8y#ϥ=ٱs+&>!ɓ͋/-oC}w~#m+ǿ+?exbcxyINNcyg糡we?4zμKP) Ӧ݋^劺3O[M|:3$$9>W#ٸ9kO}~KCǿ+cNo$.|F~jP~t}~qSy͎~4EX,zp;֭;E\>#SV}KojQQ 6M̟?~Hs(--sixbckna'돍bnoszSسz;w%-8q1lݶ\JIIcǎ?ٱڵkKV_|HKMg箽ܵ QrDn;i4ƏO?K߯w>N]4y'NΏ4y;~WWԷ?,4|vއdr+|Nlp ̙sش9*C5 ?|_gxc޼%( OAAt~+ǏoO^,^4βfl'BS֝T _ܞ'rݎߝceݺM 7掛j5}#hxgUT9k(ڽ1m=(Bbb|S<}7|jt@ݿ\Ϟ={:23hkJ}ǟ./N~<[Qq `ߧK6yhrsFYnn> ΡgY@ii\}`'qsZuv6ߙl./l`2ڻ\Y| moIA]xxx3Ύ^M.mǿ׿!ne<Ç aĈጹ&~f_C|\z|;ǿ?g:gSLu~jȹ<~b0==Yu|X\_W p܏X5^QY^(cX6c_k.1G{mwۗI=VcyF߾嗍.v|g<ن-g.Kw+~gھL*+2d{}Gxx̛$3gl6;=>]:]]Uo嫙$~o{+w~re))il6zomyl6RS&v'?C5:? (V窫L\T*&M  +ޥjԷ}o>^oHB|,WYY9L8ᄈ_ykߕOo,329~< FC T\׵ssYf-ΞʛE'êU?wH|;vbcX;>##y$'xwpՃYfm4f\-_qH*[b쩼h4 :u>W+j$#GRy} v(_6x$9-X9'?១ݪ3g>˃ch4g雓^ Ơ(..aMU;ewy̟ǎg/nM^c??;S}JK}(]=EvcaskYwGS+ߜǿ0eܻ rs+_7o SlGO}>-~GgOeFu#gaa5Emr.y^=s:iZ7Yw|<O>UUڧKw '=mQ\}8}{X?CB9>BoLuxy3gE2䣂xWػ*Mrw!𨅯hdx{k[:Vc =ztu^:7_VE/`XX] /Y!hJJʸG5-ae}ݻ>dg?aٲo2mہTgM8?[`t0WR\n|rLNKϻ?),+4݌oطyy./u_7=фURKjtzǼGH5W*b"亶tLUlK[֑6bV#X|IF;yy@](Xm>F0a ƦB Gnf>}zy~'<<Ν:ԚTy^׳cǟWPXPjkZ5c#9ԟB_K*I6ݵ<F72 (6[y(:W#P6gr}C Lg$1xf[$z}"s1ՆÉJ=>em8vLtԘboyFG#Ir+~w/G&BGȤe&'Pzr}"QS]oBBСdg]Bu&w4ixD_[6mNskͻis26'޻ b,yךrgzȰ ? JגJnRCܸ?'I/`ebj2f|0C]]աC;#Yq]ߦ:STԻ&—Hyd#%f_U)l=au &pp#RJ0Wb.f'ZJ&%sr7o $v!_Ztwy7U7?o]Ͷrgq~Z`YZe'2dRSIOp>B<('hhG(KΡ,9mItxkh|j$z{xNomDi4u<ʇ%-lҝg:u>`6֚}n$vO3d֯쁚QG*0Y\9IJ4@@6ёˢ(5C]BQOrb]lsL/-- M8`dKk )2[BńpJ-V>+2*HJY6m}4|[X8+,Vbci.^x18c0ԘV}̾_u]B(ۚ-'vmߦ>1bbB֢Frj'8T*?YY]j#$O" //eݺf<d.ޅQtUuW,F&oŧmߤ`54|SJEq:/`.mepl:;庻/K P]]MVVDG|Z/+xvL4H3)-mncUYm7J>CQȜ0hQ+0X-9O̭ai7[HUĸ@Fr`"{<27F:We1Rq*Lcl?f,eFܽQu7vqDq1~Lw-&\nb> BOa!DktҷbL8۶np{|;qh-B7{C8rv"S^r# >lXB4$-X,u{Z(DƘ]A;{P"i[^!he.?C!8/]p=((7ߜe/E B!\Ύ~~L:# @OFF6~5+WМ2cdlV|ܽV!P. 6E%\tQ"U[-IIݹL0sn!Brrի+V7z[2ux>%Kd2ѽ{g~jaܹj.ܹ;4q,C @ױc^yc1M nB!ąk3lt~u?4]ޟy`R=:60qLpǢ2k^ !Bշ-|{{9"#6l/7O뙿`)\sAf <ž(((d箽'.>H Oĺuٹs/WϮDEEt:?=B!Dr|~A!&");oϗós^߶Ю]k鷫ܹEQH<9t)6 Q٬V^^^tEQxۦM9P\\ڨ B!*~l?پO&MSOnop~Yc[-Vgn4ڇ8*jޤ@qq 1ƼB!jjslA`?zRRҰlQԻ;6Ԛ苗sؽ{0nmgPRRzZ=7OU~vy7$''߮a)D#t~(?w̷a\u`VYۘmB!\J 22 vsϽg޼%L:gLf9sՂos"Laa1߭<+Wa钗ճk&B.c<;w侉3Bqnhdx{k[:!s%2Q֯LuB!;\B!v !a4>,m6nX!2uxZӯsJڙ3'/YrF/s$wÇ ՘VZZ~Nceo[j E+BO.^Ueu54+RTޗ/BO.ސFݙ7 *Eaڴ{wVB{]mJ-[%9Ɠ9s6'Pefx,wu$`8Y'tƓWrWO1?(**V !uA%wGfCQ]1;-7?l6Bqܝ'x),,GHH2Bu^|7eSf36 __!ZEr7u35/B48M~f<t(B!DZ5s)#3!FDD-BQ));?<ҏg2f-BQ$woߖE"!B^:on0$w{k؟2ȯCj[z&08Џ~lz߅޾/ZOs!D#F3#g2r&V|jsOJ[u@oD.uZkWbjMs #\'mX>βB<ޜL6-F+X)X{k5Xmx5ZJ$su|4B>&wC,%8Rˆ= y9wj<Lޛp)7t,`t0WR\n|rLz|66' IDAT~ÞVQX)>19a2/~Op־ P!Py2Ij4}ؚ'[wPe23^*@?J,V6MjBJZ5c#9ԟB_K*I6Dl3(PTɧ]g\q.H n" pѭ31;w&5g757}K-V4(jը?6Z{zJ\,zgFFxWfAMv>ޔN-1[z`?#XQXu:֖T;WxLml*5g L5~C??7ssع};~ʛھEf \%\RA:BbzDVzy; qd5ŕl(tkBq}9& ffv736"+nB&n l![We0YYXΜ0f(pts…f_Ƴqi쭬FBVU[\ZpW]wѾe+Vyk]QJv>*6,6Op$CyQPhA!feCPmQg'{ƞ #XEDGMeT*fc꡹;")QAHeCiU#jBu> We߼R>+mVg~F!sx}$G &~(`tz>bBx2.r՜dO&| ^h8nhoQfjor6wo(' lµ$bAͩovz?ϴ`D異leCI3tƱj{oGcNAbP$w!dךiN1QЬ7W !o:!Z$f0B IB/v0ԥ7 !Z/‰}|t !97!ZGh0t˻;NOow)5#j='/[mBv #:k }R8zci#h}{=V0ъh9saQ$mJ嘦zm4}#u'kMp"vjrÿ,o!6YMXM=Y5wZ uﱊZ8WGs!DcO DՉn!jSiy!׵X3,m&EZW;~AWP=[1VF9DR=km(8AѪՠ(GF)SN%(_7=Y6Ze7[N$\ 8}7۾SVukc19Ꜧ!_@MDMNwi~|CjiKvA/I᤿ *}7^z-iد$z}"smk寭k w`.&zJO_ ?m׋C/r)qJ,9M=S__}b0:ܵ:0DѨg Ea{ o F} ]M س`وߵlV)Gע0WIt^v-gAGFrM)S[* ^N֛1qUmZ3jmk?f UHLϯ'#]˕^K< x';1ҞNPscv{vs$R~7ڷ.J3/?ڻjvo׵:w$}"Y٬yul6+g?HXb];<'p`4'l}_ }ymߗl!)5%P6FG܌$:5s%\ <=Z[\P}wq0(ػϢ՜`1vfC9kS.8xLJEԜABCQPF.\:9B\}XL'8.h4W*8](ӅMV놺~m#EQkZ"ÅO)ʚgmƜJE`Zh#3wr)(jACc)^Jk]Q0p:|뛢ԞV'Q\>ِZ܌'h`+tD;"FwDG;f5XPj~':R6'Sm4lPu]ԆpxmG塣ڡM͝j?gMm_sQ5=^DMj"ɽ(#n5(kř` 0-@͸BG0[:Vuj)a7\TwG1TR*'t zRmKw5OT(qOAr!^: (P&ش~$jG姦`3Y5+h3c.&jb7RDlBjK=#WWpO1Rq_H&^ͺlPm*v\bnX]V\ÁGZ:fsULPOgx{OnhBE bcw _L&u+jC5g:vKZqc=''y(frsYgu-mDg%/#$o݉Jp[K; mMy6 ʾ۬V^^^5ʗX7WUgHHwq#tkiSSXXzBdsanލm2޿72O} hZ-VVϾ}l:>-~۸6DR+s >Y}]a23O8nHKKd2;?z(&ÓO߷ B!N-~yOqq#ۀiS'ذ_Xׇ%8}X G?BC2e<>>nVXXlQOQ((pg$x:u@|| gI7_"zNǀHrB"xȗ_NJk/Z:ƢE|{7 ! 9sӣG}Ǐg{ !h܅DŽ},[!_t !ee(jL:ka]kёzLhhjc;vƎ޾}[KbYЖdɋoߖT <=.]:2؍1MKB<$g!m^=2i,NuB%mw:۵K@Qv>=Ν{Pxɽ˟Q|UVQj7j} ((⚗+B{( '͵+  F9#+BHH0GےҲr|!||kQ\\@``@+a]p1l6}<%% F^ӒzwfZ`F1brvއNGnz^cS\\JEE%ZB y8UTTӆo*t:_BDD^mR:vlǃNd~/522.ЎBi9]>66kaX3227XgQ/,,G.\Ю]¾}䓯֑<߶q{4Qm"ش)QOb:w?ڈVB)]iVzGbd˖l7o#22wBXX+qӍӦMHU$w}),*fٲW~E%r7scS}}UpH*=8Çr,=2&7mvqBx #K|_BBbUj5{é'I6AL,/;Hr(1BlldwzƋ>-h!!h)-/:gKSr]B\hdV"rl'Ǵu-~!IrFF80X,즋M h`9f]GC/4Iъh9^,o-䎷VoBxPwշ_!\eO DՉ,"Z)SN%(֑߳6bV#XTZ/Ax5o#}VLUh}}d#ſd۪񩼼ah8qS/$\ 8}7۾SW&x}BaPzr}"V$>[QcmThTPűj^7`㉼,&cRހW7/WEUJ F: ZebO* *L1ݻp-ӇLb2a6n@_NXf=Эf/N`.fߓ2m=`:/'2fU 1+P%Lu=rMGD YdF/_>E9 |G6׶f3>;/.]ܑgeX$,1讧P~g/® ue9<7| &JАؖM4AuF9.:}p57JͷFٓ{>}pʶ4jݕE h||P{k #{ B֞2cl4b2NB!\S놺~m#EQkZ".DV4nJs']W,ZJȰxr?;o J?Qyy|~[Nuǟ&?WA8)VEvD6ʏoSwwTpz&/:cVU=L?[a/v̧R{EQTj: !pN xf\gN!#K- J%>hcT/K֤;+\JDON 4vmܧP {1_dt2]{w*1/IDAT1b&v#MnvBBjK=#W"^_܊D%a7Gsy\j`Qo@wi[ƯKn gwҶlcg_/:AYNOK!oQ܅Y2p!-v! .N#ҌQ !KP'Pz'zRwR!5gmwŐ^Fw-BI]P_Btٝ |W&BIBnw[: !A]͐xcKB$`f' g{[:!^ݐ_Pȋ/-뮤[NB!Z$w7mٲ䝌~XK"BI{#:a!u))iZ:!IPT\@PP` G"B&ɽ(*̐B!'Iro qQQQҡ!Hro fݺMu=~/9Q !vԥKGPgypYsBa' z'xU̞=筷CUsBq "VE/`XX:ѣ 3Y8B!NF#6me)/sveV`2qB!.B2r]!he.oq }܉.B4 G2z(rF0CB!K̙{IwaUU{ǿ(rLDQphiu{,'Rdr-Qʼn43&]'ey O"p>y|^ڜksviiWٵk?..tJM$BܕjMrh,hPZBqGԺ YR\ȕBQZ/\L;PB5% h)Sy6lS! !wZ u&**B!:.lق&Mv: j:!SPTT\aՃ?/B4'}5f|hk$B*hZtq$}>=;!BTJgӤIczG!Ut[=#3 &B!}dddVk0B!J-[õkyB!趒{/?v[ݱ!X۵{=JƟB!Ȣ޻oyϜ8gBQ-s#?%֌I!Uy{߬'75cB!D܅B:B!KBQHrB!IB!D#]!c$ !u$w!.B1܅B:FBQHrB!IB!D#]!c$ !u$w!.B1EڷoKء~!K?Ax{5KtgM={>n6CCE4k֔'|JH}FQ6myK1 WݻӶ39*#DmW._GAAaMRc9w.ᎵסC;6mB̮_XE]†ht(JS?~4z+Jg&|s)iY##GB~~G,@t*'7e˴}mذ!:BINNZ$DW.gRTT\ 0v(=9{ٳ?#-*nn.^5 7K}>l0@vvߊɩC {9 ȤC1}=AAA]tb/JL?]g/X8a<{{;3YK6nV.5e=JWQW]),,4?!tg'GrsG%痾A'#''̬21!t75s^z'$1thըjjv|Ƨys'fi[Wlmm Oe_FQQS~,[:Q&PXXc0>b<%%%?pΝӾ}[rZͅ_ϊ_+@oLc.\3f2KL}'v"rr0YB7.>)9r| gdgzȹKHKJsg'&L (p$>3 26`!Qg0gL¡aƞ`xy{2.`8 4_GV9~@<=ݘ6-]HII.[6_=??MPTokN<Ǻ[qsko%#3ŋWiҋ?7F#O~//Oyy'a0i7VO\m|ՎhYN0;w ,|:E!8x4z}#F-~-篣<(4`J78;;qQ&Ms`,ӧMAߗ3fxzxQ~&F5$7U.@K%OU{#nn.2lx0O <|>_~nn.$'e0?>j>..2iL;"§hjSl,QYZߔ4([ )yGGg[[[^M/-k`JIIIc͚Eg^""擛{͢^Q.[ÃFQ)[67!㛵K_ae^LP?:FGaah4G #666tP,:CQMZ|d}|}{p|"l׺e ɗ. @˖-8yjfZW־Z+z~ZK(±Nƞ@QZpZϿ&8ȟ f^:}(7FBB?@Q5p?z8NSaԷ dpKS{I7;v2yׯ)KMb۶cooGI_[T6gLrs1cF9˧\[eiĢB=-:_^|ɟ~ۛ!V}}zۦy ?YM?{`iV\S%ǯ:h=)B&ɔw>$_T^JoL@#GrZ&OM%!s0 !BׯpӧOdѢU̟ <]hȎ֭j>Ϝ9[jZ4Xf{~~\Uh|֭ߊٰ!Ə.S;[{Yn72] `ITܹF#ݺuھZUVu|T6>757;{6HNMVaV߾~-wLߦMKޝ:f2e.\"++n]%++ o+~`Y|>xFiaaM1А@<] PmcEbE3a1"/:/]In5һӫɗSƮ]tkBB?KFfnDmISc %E.a[>xsJiM_q*tش9;#GɆ*OJJ[ 4$MHHXV]-r-EesOg>dddFTO^ak/L W(ƸlE3..L}{Z3W_ԩ\xtS@||"EE|FDJ`З̲Р\!;;/oOFa}r.D%,N;w޾=9DD, r?fMIOdt؎gɫC0MCsb]tСX&MzƏ!"b:'+;',Hޞ]>k".eJhIHH졠lvv ;f(M~qDD,(STv-9sV 4sy. ?c5jdffo!SW־ZȹK>maJϯ{/ ,lAALh4}陥7)i*\+-矹۶}//V}QoFk4qYb=xi֬)l۶˾(muhU+/-7KTo|R6lfok}''G6_EPTFbBqoʽcv 6lb|z>NvvnBk(;99YvS6>>=س瀬VVڼ²˗S;BnO QZ;1.Y *_e[IENDB`pretty_assertions-1.4.0/examples/pretty_assertion.rs000064400000000000000000000001061046102023000212260ustar 00000000000000use pretty_assertions::assert_eq; include!("standard_assertion.rs"); pretty_assertions-1.4.0/examples/pretty_assertion_v0_6_1.png000064400000000000000000000513641046102023000224540ustar 00000000000000PNG  IHDR?sBIT|dtEXtSoftwaregnome-screenshot>*tEXtCreation TimeThu 04 Mar 2021 09:59:39 GMT2 IDATxwxTUd&e&N@z4YX*JQD.V@E)ZX]P҅ХCHH!d223Ʉ~8s{{ҵ@+N7v2شi4=2yݏZ:9=ġCRq)kÃoo|n۶h;PZZVg@u!!A :΅os# \ $u]z, < رcXs:vl:3j ؏@ߐg]GnOׯ󗿌vz⏉b&gddӧoY2Bp5džۋ#Wչ3Z}Ĉy!+ff,uFGhhphw)s)?GKn:3{vӦ?pDvv}q>bqsq?%(?g͚beOa4ퟣoGb挧c\ƙgm+24KKϪ8rDh]ǯZw܁ZF'OrGȑ %%{q2i,+쟻k> x% |{8Rku5ͫQl۶~g|[1lc4&܅ ?7x^ĿwnItƏFa >N˞x+Xʓ`ٺu'/~"t:-sLꡃ(--Q XPPd^ӳ eTUUѿ_~Y^za|11Q|͝"7ns1``?B)+`m,Y>z}1wtJ$88J~i#=8j߆sf?J"%%)S?*³̦{LťϏG謩$&F>>FQslhCFa-֋_;s&[oa:{6Z0i,Ϋ>z(nM.h?ͥߙCV3}Dna>e^}m2 Gggǎ=$%e#LPFr_1r0FO??8t_[""By~@\\ 7t- .#55ՊNk_gн{,}RN??SǒOxX(fMa xHhNj/be}c`]6lVk]D>L29MCQ}Y/Ϻٹk_unw~z`2TŒ:u~9LVS SkVVvbCH6p]ߟ Ϙ172hPbeʏϏ?n`ڴ`iFr?rBfs]8eνt|Wl5R/F&,\O>y)))4?w9'I>=2ug4;ggwm?4$ͻ}l#ę>;q˂Pܞj}IMMsy]gGߔπ}Y: f~:aa!GE6n =Э[5]iT鴔;o5{ffÆ97s(b뒺@vdeei۷'* #۷M )V}bXh0:}rvERҥ#g+EÆ [\n=Ѩ{{b燯7дګw?Wk/pܙWs!EQط{( q5zqߜםUkӅ(*rveK?eߦYJͭCxT*{~wzW 1u_r:;_s'O~e99y,^p z,]2 <1LϏgg_Y盕kfZf=2g_c`O}Y]?99J߾=ٲe`{jz7̝#QU9+P^^A8Kw쟳߿Ewot~~5>>O>>L<ݻ'>>U9=>ٹvsL#:G@E~i#d>LYi9ڵ0w48yQ_(O17QXXLLL$Ws#L*SMsKoy<׏#)G=Vk 'SN/ܒ-z37 nOٳh3jKJ8pW,eҤqhZٶmgrY}yz <ͩSeEKV`ItZ6m…\ߑ/VSTTc0a( ͵l?o۷fM=sd{#,Z}eL>GgMjX\͝΢BU-gAAm_6Xz˗B>=ػ`4vOeeerT.>f?SO>BeҲ2޽3])5i?W-/.m_~V㣏hP-dsѭ[g<~^rEL9;tZ{5:jJc!nw0 ,]^^͸Q j{wM7^_F%/b2Y}+8pY~V!ڪR|hw60or🟲b7n`0uNVweNB6FB6FBHrB!IB!D#]!hc$ !m$w!.B1܅B6FBHrB!IB!D#]!hc$ !m$w!.B1܅"w%`XtK!9a Ug'3gUqJVpbߵ0~޾Y#{ejF4Ν%/su"uCoQxp -ɞBX{lk6nX矽f׷gNxcǎۋSZZFPP%`Ùr8W}ϰ {@-ƅ69^Jᚫa&Uwa>nb{-9~"..ɓ!S'ݎ Wx啥 ؏ MO=w\\V+ǫ%櫡d3En~zu'((~skI*^! ?b}3{5n=O?ytrAbqoُ'22-[vC!~|W҄T Gq}?Iez^H#h@<۲8m0qzM]s#77u4Z"艮OPoO߽X=پG7SkF} =*c^%śNN2awuXµxu7}%݅5@⮱u^}z)׮NTX>_HVAQ4iCB֦Vr?ĉ6l F0p@?Nga [N?WޯoOt;ebX,wEƓG¯V]./ą[ł|L p=Ù?;qc]W9x 6oY:ܜ@KISJbOcLPOvcN_v5)?O%D9dc|C3H_MQ=z$j:BVrlǧXT*O>Owyq \؛>}? Jl3 x;CE.%UF d&KWdL/bCxr XSXtG* T<Ď2=|WhÇxWT/" xM2Nj(M&d.݇Vx]uW-BIC)ۙw{IƢoxPJA :/O`*im0x|&II{徻dOUUU>MxxQQ8~$_˲r*SL **LJJX+-f0?.:FpRo䇢r323ԏPu y&3_痁 h7O2!<V3 H :~5~JǢ$m>ޟa0a.5}E~k?v!.蓋)1ar79p&wqIP]| C! k-?ZN̪1}ڽ!vޕt ğ[:!.hp@]s%%ewE:#Je|:rsEbBx/!Æ a˖uớHtW!E!DIBƴ8C!o/Q΂BQKׇ'qAϿf+:͚5̇hxB!ZCU7ߥ+HbSbb/P&MEyyEݶBɪUMh4L>Fa1ՍgEXX({ͼқLC{^{ƜGb֤f}BњtTZW V[g`2-ZΈyh7O7>,q(c_A,Y>s@`e:q!B\J_̗_|KPP,""#pr~y?s $"6LG9pwtb㢉`<+lذ{prAdd`H&B! 2u{׭w{<75lA(¾߮wE!ԱXVTggeXxxxйsEnvdee@QQ;*B\.ݿ{L<ō7 怷-X.3`M;ycTT@QQ1dWc^!59;TV+}'j%%f7e 5OyEQ,w&/\4\={En+!}Z]r8yKXVEi .Сc|᧘L&B!.6󜻣]o>E|$ABqjuWs8|S?d2aZn]B!$wp<|S盯n~!%1ׯyd3{K"Bf_LY C kpBʽ{S&-=ql鐄B;IB8aС o>"E"I-֋Z: !D$Iq^j'&]!5}˰_vw[گocÍAZ\GѶHrwR-3p&6|#b}8#^*É \^G;)"FnLhr:cyLj:;>BQ]zν9VWZ:fWjPfvGX T!I^󣹎mi0FCA$S{@ȭ3?ZB==4:Gd\gQ6bA}B tد?.q1V WꝊatĩ\,VXrf+XM9>BG[ńFTgNj.W xrs)l,lWouӅdWպ>m39r{ٴ|Vw&Zy> * +SŮ2=z#:D8zy2,!]eV*qqt|%^Ů2=c愾_vj`w_;(@'oW.45;X i_䕺Nh&ƳyGRsS{S۷lABOESE;Hhv&t/rl"ӅMb ʸ)H3q!|S6=2bq g͢R{ĈVYXoJhu>rQə-4YT KQ9^*VMfMag{81PPB8~÷dfnj.Hg_y/LJG,E'[,hU5XjTuX+՜kŒ3_W9*oj̨Up]/?Wsq9j L&0c,c?U¥m !DueͼYY~.\ NV3ԏBX/5_rhbuABYYQ|_'F5gL/bCxr XSXtl4 &w;˕jOc4G-Xfy*:xX1[wu1ugP<=H쭮Jݢ1Z wQ=4 `Zd RrTRو]UZ'OrK-ٖ,(`~\(ouE-fIcNt0Oņ`TΚGĝ~3: \HF}@[^CZ5g㯯7}sfvbg,\O1#*iy(0YT\ `r?yPqM$w!.S2qNhMtVEh^oBKN6$Qvꍬ/kp-DmHڃ=ez>)q}BI wåސ.B]-D;ztB6Hܝ77䣛)5#j}~ԧ~7+Z{6&~0FqNom+w'Tp9|X, c$qXTorSi("wmr?F,!Dur$BerqKeFeF}-z3geOʦbu|m@_:S-Dm*я%`R]*Kb={@Ot}PzxЧpMcЩ)۝Ks* }(۝ʌvΩgW4*zPG,1cv(.}񻃣mTor7}lD+<|(Ӣ( %l| iЩ{bâ10=ꨦ!Þ=9ȩ(.OO)iZgFڋIGӐw?!7'Rm-V<45&cLUDMCC86g4|Qxp?D(3TT;o@c;mōEGCOK $HX*t\|5ޏUV5QZouTR{-aZ8RHx4ERW+lG51d^ϖ;7&оu1WPNqX f-_j1dW9`04SSvctڱֲ*3}wt|^MiR6h-ΈV7r%x_ =?[[Pc_]@֥~MVsZV :q;ᄣvYUt6HQMMMm_s*4ZOh"|Q<LeF?I_g_cjol(?p_M%.h:jG=*_38Vxj[<}JğTԼj3dWpMVۿ?YbyG7+'TT"pD E2Qil?+*Lɽ9n>wʼn)%X*/l~BɞM/ߦpJS_Ȣ7D1XAF&[8XQbX`xcO!c:M]_ȕj?GMm_Sa=ͽ4DN *LzHhx}W_WUkBg R{nB7N&J -%*[;b*+FGʓ+(XJܓ\}6ũQ͆3ˆՉ^W_W K%xy?UwZQz-4q]ܓy[)ٚBϞFܲک.]==5FZBX̤D#}s%X2uwb8SAmQ'u 1mSkg㯯7}{V[7y,|`K;ExԘ (zƺVR[|#_VM"% q܅1]Z1H2^Ӭ+.yCmO(&@VJw)-Hr QP/ώ9V!ą$;)&&/{Xf Hpp FOlo YSILVCAA| ~#} | _ 2;2^ӳ eTUUѿ_~Y^zZ0i, 4ؾ},<23_Zjb2ᾙͶl߱~zҳgWB$;);;q>-sgV\K\| SLˋ_YiP\RJTTٹuuvaxx3yl<6 EQxgYx>֮g}N:DVzzzsY?9~39aaHj=B!.>IN2M<()iwRVZ /gLNNh4rIbWqh2OeテmOٹ,X E{ ''5k~v17Ү]8.]Bqu(i^T*.]:wM]{ iܠ<ՊJe;t+W囕k]388{Kw7^ˌ7 \ڎB'ɽ4kd6lss>|;21g][!%ɽO17QXXLLL$W^_#L*SMsƓIzi4j5:ƓW`w߸w8~F('""' @R^ﻗRRRZ3gr(.}>dfHMMh41L8^oryB4$FX}yz <ͩSe=['iٴy; .d{T#,Z?!L6oo/ mNb+(( S] ޱ];G^Vn{?"VːHrB Ǹї_|U/Z:LJ%rkB4\ ݻ;v陬#uB!Op`~+Va4[:!,IBsMгgWLa\4s{tS1q=BHro~kZ6&&m[b~:\.0П^UV˝!7E3-MÓlذ7GYYK̚5̇BCE3-K/ӧM#O;]Gbb/P&MEyyE3F+>]i3gWDiiE%55 ӧOQ#_XCG;Z?**G ӓS?^Gcsر=%2ekhJXe:vlOrrjU*gMt,[F֭I>rܩ !p?I.xHhNj/be}ck? łP) 3f܏N/,v~GpMײp2RSӱX5h|}?۵{?eeӣFrWُ>H>=\{bz ^}m)yHrwRtT;0dg<Ν{[Fw9ٳu[*-|wwe5Rycs ƌwVBBCC쟩 eX/;(3ԏ>{ !4g[**}!IroeJϗB8`CńUJC(hDϮP;/ܘ`~>,Ap>4NLJBLQOkX Z./O#h&hSy/^ -#e/ą2"T^ܠB4=Meqfr|%f ߼Redtv\oVmW_2>ܟ*#G+G!ZZ겍f^,`i+C h؄eL/bC.k}1HM|]PJ3й/s;BBzWZ'OrKa~zYw$d2ċM/0V5~?ot* et !E'LjZƅsKn|5W2" !pD`zѨdFT4D772_F !DK.fIB8&3 3 p{|S*BB[^8Ȁ-I[tBњȔmH nGF#ZlB!l$2}~Q ϯ( |[(2DrcnBa#ɽ,X ދBbBkBwührsB8|rW ]_UDK2T`̮EawuXµxu7ƃzZgN>_2Ds-< !-E \s qO ݊z~=JN=_{{|DƢ]#o]eq $(2!MxyT&?¾o(JPQ0VVb՝+2sFLU: ȈAQ[-dvyBTK*=36ۊD4 XU)ݑM VGky[)Zaj) ]04Qot}(ۓmķ-dˋj%O"u&cEX䋬| 3 M'?@~ת !c@]iR6ɏn߂JwF8<%bMTQ:.A@]Omwo۝t(4^c:^1:;FFmC7^clg?hb2sa{vo20k'w!9P;UAű‹pjo S g]W-DRB8r>?O@J~;lQyx`}^u/xסxȃBXhT@h"}6CGU-'ŊwkOջ\7Ʉ݅2 ˩<^fd:EELo[}Qf}9EAQ}w! 'wڃvu2y_TbhɸT$O@pZ5(P.;\&jj/ ~HkFל9rvhϟ_zEQ#?5ؗ܉Ç YWeu!rrORmdk'wsF&oo_މLuDS)Tb*1$awvTmjs]ӧ;vjtgPk1Ъ C$w!eI&Չ?ퟵc;d1*!4`{ρ&ZW8 8IDAT)Hyb[K(>}Z)ߥt8B"$ =CHx dm;[Cپ\r>;U=/LIB.ҽZ: !^]Cxk+B\$@b挧c[:!N]_˯,ᦛgϮWB!.2Ic2-BQ$F 6B!jHɩi[:!ITXT @``@ G"B$ɽ(,tϔB!HroR^^ҡ!5HroGcÆu;~Q !{ t%~z292!Bt:-O=kԹ;J=ɩ78!%K^d6du.ӻww&.3Y9B!BK [dWRVV^2+Vh4^B]!hs䞻Bƴ'oy*V|DB!Ѫh4;kx5cn! !Vu^\\Jnn>6m'"" Ji鐄BKNJXEi !ͪUfG ȕBqV320ݽCB!.9aϵt0o :wO?ml鐄BKF|CFwի׵t8B!%U&c cŊoZ:!*x`4,ԅB\ZerwDSBq9kCbbY. !{^?;|HO?mMu2B]Joh3Y:ԅB\Z1B!p{O??]s"B7p){wU?p=Ȩ -^qBOnmZp\,5n5Ѳ\[fJ]pS.QsE ?y|w9Ϝ93lG|X])B!UŽ7hӦ5a/6VNB!s.wc2Qz9 !9r`C!%6;v$Ӑ!Թ=F۶2!BS{^~m,!B_C,!B_{gNqJIC#BzsqKBކE! NŽ{{lmC#Bztl='N$7FNB!-bަeB!Ͻ{_iBQ !MLB!w!.B41R܅B&FBHqB!)B!D#]!hb !Mw!.B41R܅B&FBHqB!)B!D#]!hbZэBq/\"߸չVۻ3pCgDDbޱj6RFӓ;(#]vuI !8jXUUEyyŭXfqj\U= woD}(͏gi''GΞM5G1t.ٹs7VKhD yFÖ-߱(v9ժk4vڄV1mKN> ar" ホS{ػ-\J^^>={9DR ۷7;;`c2qtt*}%+U?ӦN{aooGnn>˗-;n;!~}g&Z㝔}{o$ "<~Hqq YRHΞ`_PhR|ww'W?Ѿ#͚5#-+Q_iڕW,ON|2Ӷolmm mNbB)Q_ۼysV,_ 'NS]m`0}Gn駇zzͅgΪUkӵS9BԬ➐OR5fJhEL LNf.efD0G)A7EdehٗԩAO`[ quq]K&M'|F0ip<>& nv<<4-Zwc?@pp n̞IAa.5aÆf۔`}:t0!Lۯ4>d6l܎[^}e2y|Z|s]:{;Pm`f)`ȐG%-u+Q_iڕW,͏>^ ODFŢh }Sс\Lgg'< ii۶5&1gTZh>I^Í b0heגfr"DSQcq?~Tw悿cDžrt QQqss!3S϶m_3o ؽ ]k^fr<<9 S{Yir'i'Iɳ# -5c'I:v+LVZǥKYߩ#YY9g***Lw{BB)\Σ[JplGQ̀Gk_|:%ưauN+.@U|%J+v5k(qqqߏwA5?Zk*͟5j_gF٘hĈ'pugklmm|9T-YC_X=xhKn7pu`E`fsqq&$8޽{`cfn>`Z6`ccScN%jޮ]M,˗_,g|Vr~v=??RS38o]Q;>d^;w_,WԿYjW{~6oo/4 ~:iږtFC.5]? A1n8O<(!L:\Fc|`0VjܿGgjgfz`̉0#ܲ~ɓgPrY[VVݺ݅UUa6S…(.ܹ b ߛVu[ҸXQ&S2ߏC337{~>7mSPkjƦ>6})WԿYjW{~*0?D5j^5%?B$yqÄȵyuu5Gg̘>n qe_bNuNIO?osj)m3g~ŋWHGwWZûG~TRRk^\tҒ@Zz2oP?իlظ+a/pvRrJkƧ&)) Sc{cW]*m~Wkwl޽{ߧ'ԌCX4tU;4~wڙg1o?bvE 0 8>N Y;YG11;M+ɿ޾`wL$#љ6\K<).•:{u:A|ɼVKPXvŋK6q ƦߪΝsm^/kgs*M# nS|GfDΡ-̾h+QӿYjW3j6??~t*#G !/76m̈`5 4e<[~oʁ3^3~$n'9,xN:ͅ LePQQW_ofܸQr_Y?jp91$$쓫v!jPާOO[P? :z K 8ڷ#77-[W<@ir{DZۛC>M^ Dt7oNAa!'NXΞ]{kb-gfDQsHO?CYYZ2yR?jwd}Ě?ۮf3gRY=QF;wQZZVy72I/`ooO~~27v|%J+Rai~Y99x~Cii2mjQ8khLKj9,n<=;cߩ'@f+ס3}6ųr:;sOҾ}; ٱ#+>Shuo @KOV,711=ųf''G6!$dt[rBY}ޫWwƍŹsغȩf ! Of8ӗu|}}س#7_յCm.e18#!Ӳ KZ?3_YYiBq'UBշIENDB`pretty_assertions-1.4.0/examples/standard_assertion.png000064400000000000000000000523371046102023000216540ustar 00000000000000PNG  IHDR?7sBIT|dtEXtSoftwaregnome-screenshot>*tEXtCreation TimeThu 04 Mar 2021 10:01:33 GMT. IDATxw\U2AA,Qq34WL4T@9205w6H4ŭ).r "{]`uޯp><j^oPgc?!_oѢ9رs/3XD?Iޝ׻())1ΝL<Ԯ ?% &MIQ#x?0u|kO~~gRVM&S{KHHHHH1j*\ M"{YZvz0~byg(U7%##7&qf1T49/_kYYڷoͫرA䪮+Y;~: ?YKm\x=/!!!!!_@5x=rxrC챣T7xxP6lGB;ҥUi9-ppܜF_Qxzvƚ1Yx%h֬ a|%%=zϖ ll {Ndg?$#3K gHҺu f ɑm0~qZ 8tXwӡc;y0C,b-!44ΝcooGnn~+6RBզz/ ~F\ܺu_i#˘3;7Dff`|1hGX[[uTk҅'T>NGA[ZZM=D._OQ+ׄ:Rɓg9u*oQ;x/O> ЗJ;W8;;2eil= kI\\% 5mU 7Xl|c޼PBHIIcYZRSSɑ _g%|44nȂ(Q0zp2|б S:;Qݪ:>LG&1u,=89NjۡC[.]̶{pqÔ>luQ1Ύr2hӦ%~BTvĄP _LA fMz$'JPԖ1A ڵ&,<LF`8llj/1ѣ'ehioo7KKMt֩`J'dcS-ر=K"5>S>b}'aFɻĿ x?X+> ͛ѽ[gU\_Wř>}/gg'$8x.G /EX [LkB?(0V|&'LvvA\m?B7tЖeM4bǏ%]_(>|EehrikuύqƚsDMBBBBB⿀k^!n͛"ɔS枢n:ܻ޴m 339E+kܸ.]W]( fffZӇ{wpi rt r^xE Sz׈XZZ0_㣆Uu0~bsuܵ&~t1˔4mLƹTbb."hҤa/ĥ;M_c=Fil}9EUŋW^ڴ{(hM75M6B.q>>̓L@Si*!!!!!Q;#_(,9,}gyyRRXd.s3gYYټzoz^ff6G6 %%j}jӯ, 6,)3H6PT'V!OQ='OݍNajzGh۶`E_7*oO ׈̞HN[% B;]>Ri( *ž?//mm2yҸrhJX_o܈CPжm+9 (9U(ܺ4V]1f/Ukƌ Ɉ++"''Mr ?[~^~MMBm[UbӸQ23-!!!!!!ڵXYY33g.Ш+Q;Tɩع׫+ױ !rsHİo0;\7jP={Om;[o'uWkn1xkf?ddZ߅;3Z|:;;1I:cчOЫ{x>Y6.>_gnzg}<`HHHHHHW)7x~V;ۃy+?Geh Ry~P v]'gѢXXXŋO6$,eX/ر%!JYٳE|| 5чOBhߏ? ##wOod2K`n2s-9q ƇSƿ3~k+:{EVN_" fj/ BuTNea,bCX>[  d2`tر呟жMKb]R{'//eO#n,4ǜ9<N!//uF ֜Ν^w&!!!!!@[G-4~qQQ{Z *bGhѢ9}U`%Op=G k֬^̥+%$$$$$$Su;HHHHH%KWQXXHDTfYk8/]tݍC^rztC$blZɕQygHHHHHl&L5JG.h׮VVչw/cmF_XXѣټet<i<Ҵ2}Z Almk=ՐxfiE|}FUU!&EݫO5;飚7]jִ2Ŀ ^]]q._]5t孷jӭPg(;Z\N/caڥX(6mZ)cϳ̾߶Jҵ~b4BW۷kM^=tzSػJ=뿊.aoo'xC[ԟ&Uիٳ++vӦbڥCt1  F&'ޝ@InEO`ν`Y:_Sٍizܹˤ3I;5jXr6T~#䇢D3)*z]VggWR #:a„PQ+~u )(,RYعK; K'XZZr.:w~IPLmߑ㫍U$^^C oL##>&<|4M1 ԧV8:]*//q`/DmɓcnlOll53}mao[lluǿޟ_ԪUIt=aB(𑓄TC !!!!QyPT7 Bdddqf#h/_kYYO0._bxIfMͫTڷoͫرAVHv&,-w-+ae$5g?:999<ތ%'x/(P;137#?/`O)"c//_7g޽z0!(OReL4b/'!9%Z*'? OՅ~,?S/e|t>۶ŋET'r%%#_S@BBBB򨴟---gWll9sŋW9G@.W~>vtII) 2Fc:` ZXX~;6Hu]W5Lm۶"*j/ _gW_@7_|=EEEn݂ٳprr$&"r[8:O>S}Zv4mI\./q5Bի^sss5_&_)IIMC4/` 077p̜ǃWC'5!!t։ddfiYC|m-O? CO@N#77?T_GX[[uعkvnbMlݺQ#b {klw 2ŇIf̗L'Ю]+ZzQ'1W_>\c:uj_] 3#ȅ<\cn܈+w\.c`ܚ3v\j&~a=m mA.]ʃўQϣ8;;mFBy'1ɳ:À74x-m@^򥁫DRi"֒{̛CGO K@ =z2I]:Paoo7cK6Хl޲]3>]քG" M _B]g'[U7id2NÒ%sٻ:'h:bqHuOL.?)0!6t^%<<J jV;b…HOtοP|!P +))!99 s՗C'GMI,x) W{_qII/.mNKjr\$j6rw4ժUc'J=quua֬02WϙTQ﯌677g޼P*\Kqrr䩳 !C7cįmӦ%99?י<|C6- ^e2S'ЦMK& ~lU~y'ΎLCjj6|)--7yj޺yy\"wo> TAҶI&D驔3}x@՗lڴgKx?X.tT"0`gX`:?_槟vuvvOOr) X>k +WnpejXsqq 4hXĻIu nkݍ#w߼y;D-]l'}( &bZA/_W!?{C3II)Ysbʏ!b_u橾. Eaac`nnÜ'Dzuyk?\]]8o{ /(P+G?"vZjܭĜD̹K:'L&Ӛ.f>;WUzc!~B-:TdUgœ_*7u1Ծs077^=gͱafdg,_ƍp;SVz>]9u:\ /:5E|1bNW &(h+3fUP鏇^#biiw|+ Ĵxb?fԨiFܼOػg^~ (2##M~&2r!чO:ߨ%$$$$LO ^ S{}|W~#֖`-9s3g.3Y3;ZQR\RaGK1xܠY/yBu ^aXrSM핎u+RV~@}32077ã+S]077Azu> 33 ￯2-odx9Tkg=z\Sķr߭R]|x.WWmԷoOBMd T.C88F&Y)޾6qYݘ!? 1.6iS?]zz-Q4{1N7mt}}~$7z7ر%$$$$LQ)K~~5]y3 '>N<:9y:0ɳ֤V-n܈CPжm+Uzv)n:+1"''Mt?kOH?]Dzz6]ͺ.~ OS矲TV|EO(PfddbaaG.D:Ρcxzv̌F/m߼Bcv:tcNNcM7'//m=v QQ{<ɑ4hP_P)?zw#GJJJt vPn:I̝'$_!(eǾbm]WڵR\O0u YnpC!OQ;ZWyܻu5kиQ23=!ldm"_BBBBk||ǃL\뻰co$'c^BC_.\ں2`D˾v&VVV̙ 4jJԎ_$N1ti9>;osbdgd0o w!˘XD>A{@'SR3DR=zBʪNE]_Ɗ?SƗ6t_ʞh >|CI]{LF ˣ`BKNNeϞSΖۉ<\ ZYYW)**o5nܤ1ۋ8~/vƃcowo%`&'{Wc>Gp'XZXF=}8z NP!שּׁl;&%6 5-IMn[}K|}_ɓg=++D.0'V޽L` ֮Y”mФo!i׮?n$Ǎԩ}}<8x^ϖMOqk,},bCX> IDATyB-ZArR*oُPzX_Ū_ nފѪ_zzr-O=g:p|,ʬ/ $ A( Q bc;<ڶi;! տ,ھ )~*þB* VMJ7Ծii;w BBر _$,eX/ȬD kktA鲈̞Dx,/0k <0Μ _f~\W}KR{ݻ̝ϗĉ3>~!~f} {\֜Ν^w16|C ad/u4Zhx`:gneJlΜPժHH&M~R-[kͻ~qQQ{&󟈩+ۏaпDm466֬YKWʝO ۷&2b!ݺ^0=F_*aZ,]Eaa!S̝{xzB:֬ju$$$$$W#a$tC驊ֶ&-^|޽z0~ܻY2,--XG,[V/x)~%$$$*JmXxdff3atסּ妃>+|LׄVIB(8:sB,7GQTTTkzh"  ""aWaa!Gfz_re8 vB">]nt ůDe!Mxyf {y {NUoѧJumMGT,ZϨVC?dDx{i?}.5kTJD1u__%=:x>|{1 Icg98Ԧ[75`..L7vvX2._ٛݵK6QlڴRյǎRZV ~+];Jm n_}o߮5z=O)ԏcv ާbgSRזիٳ++vӦbڥCt1O::O*ohh>S_ˢO,ɯ #F6lPZjhoL*zFȴ& p]&MHj.QÊvCݦ/0AA~(JL@ҒcGwѹKrgj|w_mp"j|c1Ԧi0u0| KmE Qۿf??kf bo[f~8khj?,o/`RLjժɤq:w„P#' ؇#_[b [m+2ztYJP,˙?CP<~ի#@u{AAAz֫^sss5Wzpбr[XXM~=QÊt9ɧL-6lGB;ҥ),TVGPݥzs ֯[2c늺mVDE?r閖xӯoO!EEEn݂ٳprr$&"r[8:O_Qxzvƚ1YxeA}9z_V\|]6M~b"+C` kz4dHII9Ba?/ss } 6ԏt{{;rsC,_AcjۻcmmEzzmb}ڹu7unF|2쭱ߍ7`&M2_KJ3bNk ?T~rvvb֍8OB_ ('OԩGW+-ɁbkgTn řo^ΪU_;x~o8%++f͚ɇ8::PRRѣl*<U? ՏkYhM7dKQ(=fKJ*|(hCL6H=4l䊟hUOz{¬YadfeS3ɩ_mnnμy,_koUH/mKqrr䩳 !Co6-XյΜڶiYn*:6mZ7!T5pC(꧴tnތ{s)(ywo> TBҶQ&DCL2uVK%ϙ3/w4s-V SRXqr$(ȗEGCWl۶5СC[.]̶{pqÔ>(>ct1P֯?ߔz9xaBe\={gitk|##_z?T?kP-?]Ф<>nx?uҒӕiTWmmlINNW,Z\3k^5Ѵi#rg^Lb=<Sxj~2Lkkx,ztW_m6ڴROȾeQ矲*YXK/b ͩWsssjX섹•oܸ. ʮ0~9u:\ / ."1bcۿx4GPoh||Y?d];C`;:b](>QMqVOWeѥ}BӖneg ƟP}.%P( L&F +k\.m̘ۖ1f%0U]#k]C9߹Xt"5k)u̙ 9s_Q̚Dz().0tw@itMֶR~~( SĮ_ $6*o ݨC~BJGSYܺPn W)bToFffxxtPqYZѣ <0p"%13..>(H¢Be9 {˛}<0/^#2{"ڛGaii!(\gwTr9-U>ۓiŠX4?62̚IU䋨t !~!iK7ZHD]k}3bWʩUw ]:3g.qfaffVaʲXzT(.-vSӄu%lm4A_NN mFF994mYwB颿&3شg*|mօUPطu)KeWYt_ oFF&xB>gWT_f<  Сc;vZ>S~TG6n?^^>۶{2yғ#53hР\SDFW;t;o1'NIB74Q?}ϟںF ڵk镥\|`:6ΐCSԎU^yp]h}?(5 33[6nmM6oަq!Mb쩬^5˗'0c6iw_gs-nR#PT4bS[ ʵM6*7,Bkbu/ OS.#m_k}(E~kkܹKff6;</͝;_(jg1k<5<Յ;~[X z즇XYY33g.Ш+Q;~avvvb8u*ƨBMX$ֶGwo͞/6"1_~Sٱs/!ԯWWcm]CWoeh(E_^~'2{V+V~\.'0`,'O0{7])Ǘ۠ICӮ]3~HƏS+XOtP"_}˗r;>ϲۃI:<&1l>_9<N!//uF F|yg`~{7ohUpg(*dOœG\Οe^aax35B*[, 9)7 :v=jQʎ{Y m۴yڝ~_C~QY, ?PPPX)T%kPMKKܹK(  ǎS'$,eX/ȬD kktA@hccMGQԮ<*Re-ZJ۟qtߛի #:~a2e|4lX,w}5rWƗ1GC;sVS|r]q,YJw&3wb>_:'Ψ6I4BL]6 Ubc֜Ν^w1Ԯt/muwwW𚠚&/H^~-O'gѢXXXŋm.~,ESOã ?UG3|!/d?tcALi/>o=66Oh6|h0!88&##}n&4:VB 4{1F:܏ѢEs1=Ks+Sfs͹$$)4iҐ떲lZnӏ눊h4DLe_ %U~ 6'jsg k֬^̥+Gօ[nVXg BSWU׏DmwcABBB?*]:Ю]+s^ 7|*230q:rA> NcNHkBU$!a9!͛TKɾ*ڏn/p < "b7 9z4l+iؠ>YrTã+G4h޿|YRR;;[ZȐqsU?SGȴԮmk7M"_BJFF&=H;0Wtɘ"U >{~и 6 ԟ& ;řy>ɑwLJPן741ZcGwzbLoך^zf,ma :vl{'!!!!Ĩמ=2m1Ehؠ>j^mw]&MHj~Ґ;8f8rx߯k(rț6mZr.jűhӦ%<:44;m|  P^WUٿ_%w:*?m`1XXXOxr-_ 2c<];71kf*OnwZ#IDAT[i֬B3~joff&h|CquW!MS|<+:zi*''ޝP8cSNULJ8*m& QQ;r*xyM ++[uҒ:u;w1iyiϢN0._bxIfM : Pb嗀i!J`ܽ[ GB_lT׽{'.^]ٽɎ-[+9u:3R%ݻw=ט DD[iں(ߵk7`i9]n cӯ4O,2Q#nތ7g~ņӡc;y0C,b^KKK׷']ށ\{. <<SXX%>슍5gc.xJRS`% 1vlwCWpwo='0j?vnbMlݺQ#b {kkc޼PtrqtgMpc3F~~wKWdR4 LkU7j@OWD^۶mET^#YhYY٪wfg?1]};7zn<߬I~}ǟ`Y͒>= 'O 3m\GGJJ9z4-YŃsu'h!z{0ljִ! #՚RĴ>i!ll {Ndg?$#3K&~vL }{wHO`ݺMܵOLh;^yb w GG{vD}3>?Ķ u< ->^ :"˹u6~(*zT=r9qskqAdff ƇPb~Ʒ C\xmR)}xɚ53f|Hv D.8̛#ǃ8Cdffގo (޻,:# kI\\% 5mE?/mQ35k ޾6))ii]|]q|@lU~y'ΎLCjj6|/:!t}[L&祗T׫WFmY2UdX[ ''G{Z|:UƧp3~HwM62||>rBA۪۷܂cO+X~ʿPMNTo0!dL:%KwNuΠ !Zqr$(ȗUf?1| >| 2 3iO+R >i!>hM7dKQ(=f*Mquua֬02WϹܬ/lEa#W|GSZ5~L~͛]5xuo݂|.^1Xhć ae.֮Gqvv0pdO@6-Jf:_ /Qnq={gitk|}x7:P(<|96Y5HMNN%,, e~Fj˿II)qw`j/52G\i]WJlNޭr^hF~c[*,O?㗭駝:._F`f&G.sv]֩S{TݻL/ԫ_[ʪCz}&C?ww7ޡotЖe}fJlKElT>̙ tI5 _"#CKHu_LM?\KicM̹K%Рa}&W5!~YYDGS]]1xpQS0ԯWĻIZe/mhDzuyk?TϮ. g?G{RR8w>"3,n&%b]avOg×ߓ"!>|W_ݍs.U+_ C| G[Y|Fr393fLma~ƈo ݻSO@F&qC11d4iPqo޼)2L9%)֭SrG<"1NN2:thԭ[3}ILqw\njԯ{nݷ޹EU7#!qU֭-/H[ZmtS,-^PRR@(+lV T.rYQ0r1`?Y`3A9==n'u.Z̞5 a[8q"]4֬HEyΎ#2"+B4i"iimed| #qFc| xvyd˖VGAO .\(",|s]]G@nyݚܞWU`N|ߠg|={vr32sqOrq#(.Q2f$%_l仺:1h#GN9w ll(f`~o]ڻCv1XoZ!zZL[[66ւZ~RŰaw9n4*V?a(5`zMܗO Qx5TW]u{#YYg:C`|օ,g| **(.QR\ҥ~*Uw99s^:F@;G9oft ё#'lYL&E?Z먀Z68Zp3%{' ࡇ"Q(lIN9wXdJoޮgS1ߩP0e 㗫MFxg{1d/s(ghG+;ͬ/w[ȓSe';gCޠ#Q۵Va#υ Ex/Cp'<=[l!ͥ5٘6+CYX~$!!!kBP맨VرF<=VTǦ!ɺUJ۵:aך:u 2>0uu 8*5ΝX[3Ezx;mw(XIAa ypS^QkP*{HKWf1xn]tlѴ2jHA-_| wJ)))g:iYF6$[6w[R%Sט[:m؜6D:RS3y'&9.9VWŏ!>}wb,c4Hn;Dj%}Nۛ"k ZΟ/Z6Rm_KXVe„qcҢ槟Dl1TJ~BO$f4J*+k(,,1ZsCW0%}ary>X7ʕaY{YX-!!!q ZSSKb!\> ^_} P( OVܜۛDu%'zUN '|!vv՝05o- ##G2ǎbS*uxVKq/1oa,Yٳz`AA _x+8;;w~]! x,&:MNY-zuԒ%~| AAz>} 2W_EYEQNNù~:Nh]S'SXXR3q'EE|a,79j= ҪfLn+/"##쌏=7q8QS(ݠFдa{{;pvr::"}^m={iSVV2 $*1?+b7d+99~DSs3n.SG} xѸ;z{J=E}kTW_"11իzeC?rT lFmm璷d*j[Y ǎQQѽ~BOBA^e*c]ƎOd8u*7Wg~K?,Y>}evk*)o N#"xBV,DJaa ;> ә5K$CCu%M{J]] v;eZ&5o AA 8Ж+JM~QQ)ku Rӳzmџ~r"#֡T8rBW9&o(&kֆlb@֯[gdⷶZa988MSSO#LKhmmȈuhZ믐CLL,^^c+;\^&ows25+CGx*j s?>L~b7jHr{7aa[HL:d9ȈQL56Ljhl[cc !/Kƿ1\eKZ5W3K?0lS0qx{lMMMmɛCh4n_KcSv;;;;Kb~ @3thV8g\-d/vdOolJ|fxD3ֻe?Lߵk/ ~)ޓɠTEʡzSQQMX>xmҲ8z`YY-!!!q 7~ ~ܵ$Ǯ~̙SyYܯב+f0d8ggGn}VIBBBBB RU△g ~wUU07Y# 15-. ߣ*U}U0ŽC(iW_c574hnQszg<}}I6hUuIENDB`pretty_assertions-1.4.0/examples/standard_assertion.rs000064400000000000000000000010141046102023000214760ustar 00000000000000#[derive(Debug, PartialEq)] struct Foo { lorem: &'static str, ipsum: u32, dolor: Result, } fn compare() { let x = Some(Foo { lorem: "Hello World!", ipsum: 42, dolor: Ok("hey".to_string()), }); let y = Some(Foo { lorem: "Hello Wrold!", ipsum: 42, dolor: Ok("hey ho!".to_string()), }); assert_eq!(x, y); } fn main() { let result = std::panic::catch_unwind(compare); assert!(result.is_err(), "example did not panic"); } pretty_assertions-1.4.0/src/lib.rs000064400000000000000000000336551046102023000153460ustar 00000000000000//! # Pretty Assertions //! //! When writing tests in Rust, you'll probably use `assert_eq!(a, b)` _a lot_. //! //! If such a test fails, it will present all the details of `a` and `b`. //! But you have to spot the differences yourself, which is not always straightforward, //! like here: //! //! ![standard assertion](https://raw.githubusercontent.com/rust-pretty-assertions/rust-pretty-assertions/2d2357ff56d22c51a86b2f1cfe6efcee9f5a8081/examples/standard_assertion.png) //! //! Wouldn't that task be _much_ easier with a colorful diff? //! //! ![pretty assertion](https://raw.githubusercontent.com/rust-pretty-assertions/rust-pretty-assertions/2d2357ff56d22c51a86b2f1cfe6efcee9f5a8081/examples/pretty_assertion.png) //! //! Yep — and you only need **one line of code** to make it happen: //! //! ```rust //! use pretty_assertions::{assert_eq, assert_ne}; //! ``` //! //!
//! Show the example behind the screenshots above. //! //! ```rust,should_panic //! // 1. add the `pretty_assertions` dependency to `Cargo.toml`. //! // 2. insert this line at the top of each module, as needed //! use pretty_assertions::{assert_eq, assert_ne}; //! //! #[derive(Debug, PartialEq)] //! struct Foo { //! lorem: &'static str, //! ipsum: u32, //! dolor: Result, //! } //! //! let x = Some(Foo { lorem: "Hello World!", ipsum: 42, dolor: Ok("hey".to_string())}); //! let y = Some(Foo { lorem: "Hello Wrold!", ipsum: 42, dolor: Ok("hey ho!".to_string())}); //! //! assert_eq!(x, y); //! ``` //!
//! //! ## Tip //! //! Specify it as [`[dev-dependencies]`](http://doc.crates.io/specifying-dependencies.html#development-dependencies) //! and it will only be used for compiling tests, examples, and benchmarks. //! This way the compile time of `cargo build` won't be affected! //! //! Also add `#[cfg(test)]` to your `use` statements, like this: //! //! ```rust //! #[cfg(test)] //! use pretty_assertions::{assert_eq, assert_ne}; //! ``` //! //! ## Note //! //! * Since `Rust 2018` edition, you need to declare //! `use pretty_assertions::{assert_eq, assert_ne};` per module. //! Before you would write `#[macro_use] extern crate pretty_assertions;`. //! * The replacement is only effective in your own crate, not in other libraries //! you include. //! * `assert_ne` is also switched to multi-line presentation, but does _not_ show //! a diff. //! //! ## Features //! //! Features provided by the crate are: //! //! - `std`: Use the Rust standard library. Enabled by default. //! Exactly one of `std` and `alloc` is required. //! - `alloc`: Use the `alloc` crate. //! Exactly one of `std` and `alloc` is required. //! - `unstable`: opt-in to unstable features that may not follow Semantic Versioning. //! The implementation behind this feature is subject to change without warning between patch versions. #![cfg_attr(not(feature = "std"), no_std)] #![deny(clippy::all, missing_docs, unsafe_code)] #[cfg(feature = "alloc")] #[macro_use] extern crate alloc; use core::fmt::{self, Debug, Display}; mod printer; /// A comparison of two values. /// /// Where both values implement `Debug`, the comparison can be displayed as a pretty diff. /// /// ``` /// use pretty_assertions::Comparison; /// /// print!("{}", Comparison::new(&123, &134)); /// ``` /// /// The values may have different types, although in practice they are usually the same. pub struct Comparison<'a, TLeft, TRight> where TLeft: ?Sized, TRight: ?Sized, { left: &'a TLeft, right: &'a TRight, } impl<'a, TLeft, TRight> Comparison<'a, TLeft, TRight> where TLeft: ?Sized, TRight: ?Sized, { /// Store two values to be compared in future. /// /// Expensive diffing is deferred until calling `Debug::fmt`. pub fn new(left: &'a TLeft, right: &'a TRight) -> Comparison<'a, TLeft, TRight> { Comparison { left, right } } } impl<'a, TLeft, TRight> Display for Comparison<'a, TLeft, TRight> where TLeft: Debug + ?Sized, TRight: Debug + ?Sized, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // To diff arbitary types, render them as debug strings let left_debug = format!("{:#?}", self.left); let right_debug = format!("{:#?}", self.right); // And then diff the debug output printer::write_header(f)?; printer::write_lines(f, &left_debug, &right_debug) } } /// A comparison of two strings. /// /// In contrast to [`Comparison`], which uses the [`core::fmt::Debug`] representation, /// `StrComparison` uses the string values directly, resulting in multi-line output for multiline strings. /// /// ``` /// use pretty_assertions::StrComparison; /// /// print!("{}", StrComparison::new("foo\nbar", "foo\nbaz")); /// ``` /// /// ## Value type bounds /// /// Any value that can be referenced as a [`str`] via [`AsRef`] may be used: /// /// ``` /// use pretty_assertions::StrComparison; /// /// #[derive(PartialEq)] /// struct MyString(String); /// /// impl AsRef for MyString { /// fn as_ref(&self) -> &str { /// &self.0 /// } /// } /// /// print!( /// "{}", /// StrComparison::new( /// &MyString("foo\nbar".to_owned()), /// &MyString("foo\nbaz".to_owned()), /// ), /// ); /// ``` /// /// The values may have different types, although in practice they are usually the same. pub struct StrComparison<'a, TLeft, TRight> where TLeft: ?Sized, TRight: ?Sized, { left: &'a TLeft, right: &'a TRight, } impl<'a, TLeft, TRight> StrComparison<'a, TLeft, TRight> where TLeft: AsRef + ?Sized, TRight: AsRef + ?Sized, { /// Store two values to be compared in future. /// /// Expensive diffing is deferred until calling `Debug::fmt`. pub fn new(left: &'a TLeft, right: &'a TRight) -> StrComparison<'a, TLeft, TRight> { StrComparison { left, right } } } impl<'a, TLeft, TRight> Display for StrComparison<'a, TLeft, TRight> where TLeft: AsRef + ?Sized, TRight: AsRef + ?Sized, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { printer::write_header(f)?; printer::write_lines(f, self.left.as_ref(), self.right.as_ref()) } } /// Asserts that two expressions are equal to each other (using [`PartialEq`]). /// /// On panic, this macro will print a diff derived from [`Debug`] representation of /// each value. /// /// This is a drop in replacement for [`core::assert_eq!`]. /// You can provide a custom panic message if desired. /// /// # Examples /// /// ``` /// use pretty_assertions::assert_eq; /// /// let a = 3; /// let b = 1 + 2; /// assert_eq!(a, b); /// /// assert_eq!(a, b, "we are testing addition with {} and {}", a, b); /// ``` #[macro_export] macro_rules! assert_eq { ($left:expr, $right:expr$(,)?) => ({ $crate::assert_eq!(@ $left, $right, "", ""); }); ($left:expr, $right:expr, $($arg:tt)*) => ({ $crate::assert_eq!(@ $left, $right, ": ", $($arg)+); }); (@ $left:expr, $right:expr, $maybe_colon:expr, $($arg:tt)*) => ({ match (&($left), &($right)) { (left_val, right_val) => { if !(*left_val == *right_val) { use $crate::private::CreateComparison; ::core::panic!("assertion failed: `(left == right)`{}{}\ \n\ \n{}\ \n", $maybe_colon, format_args!($($arg)*), (left_val, right_val).create_comparison() ) } } } }); } /// Asserts that two expressions are equal to each other (using [`PartialEq`]). /// /// On panic, this macro will print a diff derived from each value's [`str`] representation. /// See [`StrComparison`] for further details. /// /// This is a drop in replacement for [`core::assert_eq!`]. /// You can provide a custom panic message if desired. /// /// # Examples /// /// ``` /// use pretty_assertions::assert_str_eq; /// /// let a = "foo\nbar"; /// let b = ["foo", "bar"].join("\n"); /// assert_str_eq!(a, b); /// /// assert_str_eq!(a, b, "we are testing concatenation with {} and {}", a, b); /// ``` #[macro_export] macro_rules! assert_str_eq { ($left:expr, $right:expr$(,)?) => ({ $crate::assert_str_eq!(@ $left, $right, "", ""); }); ($left:expr, $right:expr, $($arg:tt)*) => ({ $crate::assert_str_eq!(@ $left, $right, ": ", $($arg)+); }); (@ $left:expr, $right:expr, $maybe_colon:expr, $($arg:tt)*) => ({ match (&($left), &($right)) { (left_val, right_val) => { if !(*left_val == *right_val) { ::core::panic!("assertion failed: `(left == right)`{}{}\ \n\ \n{}\ \n", $maybe_colon, format_args!($($arg)*), $crate::StrComparison::new(left_val, right_val) ) } } } }); } /// Asserts that two expressions are not equal to each other (using [`PartialEq`]). /// /// On panic, this macro will print the values of the expressions with their /// [`Debug`] representations. /// /// This is a drop in replacement for [`core::assert_ne!`]. /// You can provide a custom panic message if desired. /// /// # Examples /// /// ``` /// use pretty_assertions::assert_ne; /// /// let a = 3; /// let b = 2; /// assert_ne!(a, b); /// /// assert_ne!(a, b, "we are testing that the values are not equal"); /// ``` #[macro_export] macro_rules! assert_ne { ($left:expr, $right:expr$(,)?) => ({ $crate::assert_ne!(@ $left, $right, "", ""); }); ($left:expr, $right:expr, $($arg:tt)+) => ({ $crate::assert_ne!(@ $left, $right, ": ", $($arg)+); }); (@ $left:expr, $right:expr, $maybe_colon:expr, $($arg:tt)+) => ({ match (&($left), &($right)) { (left_val, right_val) => { if *left_val == *right_val { ::core::panic!("assertion failed: `(left != right)`{}{}\ \n\ \nBoth sides:\ \n{:#?}\ \n\ \n", $maybe_colon, format_args!($($arg)+), left_val ) } } } }); } /// Asserts that a value matches a pattern. /// /// On panic, this macro will print a diff derived from [`Debug`] representation of /// the value, and a string representation of the pattern. /// /// This is a drop in replacement for [`core::assert_matches::assert_matches!`]. /// You can provide a custom panic message if desired. /// /// # Examples /// /// ``` /// use pretty_assertions::assert_matches; /// /// let a = Some(3); /// assert_matches!(a, Some(_)); /// /// assert_matches!(a, Some(value) if value > 2, "we are testing {:?} with a pattern", a); /// ``` /// /// # Features /// /// Requires the `unstable` feature to be enabled. /// /// **Please note:** implementation under the `unstable` feature may be changed between /// patch versions without warning. #[cfg(feature = "unstable")] #[macro_export] macro_rules! assert_matches { ($left:expr, $( $pattern:pat )|+ $( if $guard: expr )? $(,)?) => ({ match $left { $( $pattern )|+ $( if $guard )? => {} ref left_val => { $crate::assert_matches!( @ left_val, ::core::stringify!($($pattern)|+ $(if $guard)?), "", "" ); } } }); ($left:expr, $( $pattern:pat )|+ $( if $guard: expr )?, $($arg:tt)+) => ({ match $left { $( $pattern )|+ $( if $guard )? => {} ref left_val => { $crate::assert_matches!( @ left_val, ::core::stringify!($($pattern)|+ $(if $guard)?), ": ", $($arg)+ ); } } }); (@ $left:expr, $right:expr, $maybe_colon:expr, $($arg:tt)*) => ({ match (&($left), &($right)) { (left_val, right_val) => { // Use the Display implementation to display the pattern, // as using Debug would add another layer of quotes to the output. struct Pattern<'a>(&'a str); impl ::core::fmt::Debug for Pattern<'_> { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { ::core::fmt::Display::fmt(self.0, f) } } ::core::panic!("assertion failed: `(left matches right)`{}{}\ \n\ \n{}\ \n", $maybe_colon, format_args!($($arg)*), $crate::Comparison::new(left_val, &Pattern(right_val)) ) } } }); } // Not public API. Used by the expansion of this crate's assert macros. #[doc(hidden)] pub mod private { #[cfg(feature = "alloc")] use alloc::string::String; pub trait CompareAsStrByDefault: AsRef {} impl CompareAsStrByDefault for str {} impl CompareAsStrByDefault for String {} impl CompareAsStrByDefault for &T {} pub trait CreateComparison { type Comparison; fn create_comparison(self) -> Self::Comparison; } impl<'a, T, U> CreateComparison for &'a (T, U) { type Comparison = crate::Comparison<'a, T, U>; fn create_comparison(self) -> Self::Comparison { crate::Comparison::new(&self.0, &self.1) } } impl<'a, T, U> CreateComparison for (&'a T, &'a U) where T: CompareAsStrByDefault + ?Sized, U: CompareAsStrByDefault + ?Sized, { type Comparison = crate::StrComparison<'a, T, U>; fn create_comparison(self) -> Self::Comparison { crate::StrComparison::new(self.0, self.1) } } } pretty_assertions-1.4.0/src/printer.rs000064400000000000000000000430471046102023000162570ustar 00000000000000#[cfg(feature = "alloc")] use alloc::format; use core::fmt; use yansi::{ Color::{Fixed, Green, Red, Unset}, Style, }; macro_rules! paint { ($f:expr, $colour:expr, $fmt:expr, $($args:tt)*) => ( write!($f, "{}", $colour.paint(format!($fmt, $($args)*))) ) } const SIGN_RIGHT: char = '>'; // + > → const SIGN_LEFT: char = '<'; // - < ← /// Present the diff output for two mutliline strings in a pretty, colorised manner. pub(crate) fn write_header(f: &mut fmt::Formatter) -> fmt::Result { writeln!( f, "{} {} / {} :", Style::new(Unset).bold().paint("Diff"), Red.paint(format!("{} left", SIGN_LEFT)), Green.paint(format!("right {}", SIGN_RIGHT)) ) } /// Delay formatting this deleted chunk until later. /// /// It can be formatted as a whole chunk by calling `flush`, or the inner value /// obtained with `take` for further processing (such as an inline diff). #[derive(Default)] struct LatentDeletion<'a> { // The most recent deleted line we've seen value: Option<&'a str>, // The number of deleted lines we've seen, including the current value count: usize, } impl<'a> LatentDeletion<'a> { /// Set the chunk value. fn set(&mut self, value: &'a str) { self.value = Some(value); self.count += 1; } /// Take the underlying chunk value, if it's suitable for inline diffing. /// /// If there is no value or we've seen more than one line, return `None`. fn take(&mut self) -> Option<&'a str> { if self.count == 1 { self.value.take() } else { None } } /// If a value is set, print it as a whole chunk, using the given formatter. /// /// If a value is not set, reset the count to zero (as we've called `flush` twice, /// without seeing another deletion. Therefore the line in the middle was something else). fn flush(&mut self, f: &mut TWrite) -> fmt::Result { if let Some(value) = self.value { paint!(f, Red, "{}{}", SIGN_LEFT, value)?; writeln!(f)?; self.value = None; } else { self.count = 0; } Ok(()) } } // Adapted from: // https://github.com/johannhof/difference.rs/blob/c5749ad7d82aa3d480c15cb61af9f6baa08f116f/examples/github-style.rs // Credits johannhof (MIT License) /// Present the diff output for two mutliline strings in a pretty, colorised manner. pub(crate) fn write_lines( f: &mut TWrite, left: &str, right: &str, ) -> fmt::Result { let diff = ::diff::lines(left, right); let mut changes = diff.into_iter().peekable(); let mut previous_deletion = LatentDeletion::default(); while let Some(change) = changes.next() { match (change, changes.peek()) { // If the text is unchanged, just print it plain (::diff::Result::Both(value, _), _) => { previous_deletion.flush(f)?; writeln!(f, " {}", value)?; } // Defer any deletions to next loop (::diff::Result::Left(deleted), _) => { previous_deletion.flush(f)?; previous_deletion.set(deleted); } // If we're being followed by more insertions, don't inline diff (::diff::Result::Right(inserted), Some(::diff::Result::Right(_))) => { previous_deletion.flush(f)?; paint!(f, Green, "{}{}", SIGN_RIGHT, inserted)?; writeln!(f)?; } // Otherwise, check if we need to inline diff with the previous line (if it was a deletion) (::diff::Result::Right(inserted), _) => { if let Some(deleted) = previous_deletion.take() { write_inline_diff(f, deleted, inserted)?; } else { previous_deletion.flush(f)?; paint!(f, Green, "{}{}", SIGN_RIGHT, inserted)?; writeln!(f)?; } } }; } previous_deletion.flush(f)?; Ok(()) } /// Group character styling for an inline diff, to prevent wrapping each single /// character in terminal styling codes. /// /// Styles are applied automatically each time a new style is given in `write_with_style`. struct InlineWriter<'a, Writer> { f: &'a mut Writer, style: Style, } impl<'a, Writer> InlineWriter<'a, Writer> where Writer: fmt::Write, { fn new(f: &'a mut Writer) -> Self { InlineWriter { f, style: Style::new(Unset), } } /// Push a new character into the buffer, specifying the style it should be written in. fn write_with_style(&mut self, c: &char, style: Style) -> fmt::Result { // If the style is the same as previously, just write character if style == self.style { write!(self.f, "{}", c)?; } else { // Close out previous style self.style.fmt_suffix(self.f)?; // Store new style and start writing it style.fmt_prefix(self.f)?; write!(self.f, "{}", c)?; self.style = style; } Ok(()) } /// Finish any existing style and reset to default state. fn finish(&mut self) -> fmt::Result { // Close out previous style self.style.fmt_suffix(self.f)?; writeln!(self.f)?; self.style = Style::new(Unset); Ok(()) } } /// Format a single line to show an inline diff of the two strings given. /// /// The given strings should not have a trailing newline. /// /// The output of this function will be two lines, each with a trailing newline. fn write_inline_diff(f: &mut TWrite, left: &str, right: &str) -> fmt::Result { let diff = ::diff::chars(left, right); let mut writer = InlineWriter::new(f); // Print the left string on one line, with differences highlighted let light = Style::new(Red); let heavy = Style::new(Red).bg(Fixed(52)).bold(); writer.write_with_style(&SIGN_LEFT, light)?; for change in diff.iter() { match change { ::diff::Result::Both(value, _) => writer.write_with_style(value, light)?, ::diff::Result::Left(value) => writer.write_with_style(value, heavy)?, _ => (), } } writer.finish()?; // Print the right string on one line, with differences highlighted let light = Style::new(Green); let heavy = Style::new(Green).bg(Fixed(22)).bold(); writer.write_with_style(&SIGN_RIGHT, light)?; for change in diff.iter() { match change { ::diff::Result::Both(value, _) => writer.write_with_style(value, light)?, ::diff::Result::Right(value) => writer.write_with_style(value, heavy)?, _ => (), } } writer.finish() } #[cfg(test)] mod test { use super::*; #[cfg(feature = "alloc")] use alloc::string::String; // ANSI terminal codes used in our outputs. // // Interpolate these into test strings to make expected values easier to read. const RED_LIGHT: &str = "\u{1b}[31m"; const GREEN_LIGHT: &str = "\u{1b}[32m"; const RED_HEAVY: &str = "\u{1b}[1;48;5;52;31m"; const GREEN_HEAVY: &str = "\u{1b}[1;48;5;22;32m"; const RESET: &str = "\u{1b}[0m"; /// Given that both of our diff printing functions have the same /// type signature, we can reuse the same test code for them. /// /// This could probably be nicer with traits! fn check_printer(printer: TPrint, left: &str, right: &str, expected: &str) where TPrint: Fn(&mut String, &str, &str) -> fmt::Result, { let mut actual = String::new(); printer(&mut actual, left, right).expect("printer function failed"); // Cannot use IO without stdlib #[cfg(feature = "std")] println!( "## left ##\n\ {}\n\ ## right ##\n\ {}\n\ ## actual diff ##\n\ {}\n\ ## expected diff ##\n\ {}", left, right, actual, expected ); assert_eq!(actual, expected); } #[test] fn write_inline_diff_empty() { let left = ""; let right = ""; let expected = format!( "{red_light}<{reset}\n\ {green_light}>{reset}\n", red_light = RED_LIGHT, green_light = GREEN_LIGHT, reset = RESET, ); check_printer(write_inline_diff, left, right, &expected); } #[test] fn write_inline_diff_added() { let left = ""; let right = "polymerase"; let expected = format!( "{red_light}<{reset}\n\ {green_light}>{reset}{green_heavy}polymerase{reset}\n", red_light = RED_LIGHT, green_light = GREEN_LIGHT, green_heavy = GREEN_HEAVY, reset = RESET, ); check_printer(write_inline_diff, left, right, &expected); } #[test] fn write_inline_diff_removed() { let left = "polyacrylamide"; let right = ""; let expected = format!( "{red_light}<{reset}{red_heavy}polyacrylamide{reset}\n\ {green_light}>{reset}\n", red_light = RED_LIGHT, green_light = GREEN_LIGHT, red_heavy = RED_HEAVY, reset = RESET, ); check_printer(write_inline_diff, left, right, &expected); } #[test] fn write_inline_diff_changed() { let left = "polymerase"; let right = "polyacrylamide"; let expected = format!( "{red_light}poly{reset}{green_heavy}ac{reset}{green_light}r{reset}{green_heavy}yl{reset}{green_light}a{reset}{green_heavy}mid{reset}{green_light}e{reset}\n", red_light = RED_LIGHT, green_light = GREEN_LIGHT, red_heavy = RED_HEAVY, green_heavy = GREEN_HEAVY, reset = RESET, ); check_printer(write_inline_diff, left, right, &expected); } /// If one of our strings is empty, it should not be shown at all in the output. #[test] fn write_lines_empty_string() { let left = ""; let right = "content"; let expected = format!( "{green_light}>content{reset}\n", green_light = GREEN_LIGHT, reset = RESET, ); check_printer(write_lines, left, right, &expected); } /// Realistic multiline struct diffing case. #[test] fn write_lines_struct() { let left = r#"Some( Foo { lorem: "Hello World!", ipsum: 42, dolor: Ok( "hey", ), }, )"#; let right = r#"Some( Foo { lorem: "Hello Wrold!", ipsum: 42, dolor: Ok( "hey ho!", ), }, )"#; let expected = format!( r#" Some( Foo {{ {red_light}< lorem: "Hello W{reset}{red_heavy}o{reset}{red_light}rld!",{reset} {green_light}> lorem: "Hello Wr{reset}{green_heavy}o{reset}{green_light}ld!",{reset} ipsum: 42, dolor: Ok( {red_light}< "hey",{reset} {green_light}> "hey{reset}{green_heavy} ho!{reset}{green_light}",{reset} ), }}, ) "#, red_light = RED_LIGHT, red_heavy = RED_HEAVY, green_light = GREEN_LIGHT, green_heavy = GREEN_HEAVY, reset = RESET, ); check_printer(write_lines, left, right, &expected); } /// Relistic multiple line chunks /// /// We can't support realistic line diffing in large blocks /// (also, it's unclear how usefult this is) /// /// So if we have more than one line in a single removal chunk, disable inline diffing. #[test] fn write_lines_multiline_block() { let left = r#"Proboscis Cabbage"#; let right = r#"Probed Caravaggio"#; let expected = format!( r#"{red_light}Probed{reset} {green_light}>Caravaggio{reset} "#, red_light = RED_LIGHT, green_light = GREEN_LIGHT, reset = RESET, ); check_printer(write_lines, left, right, &expected); } /// Single deletion line, multiple insertions - no inline diffing. #[test] fn write_lines_multiline_insert() { let left = r#"Cabbage"#; let right = r#"Probed Caravaggio"#; let expected = format!( r#"{red_light}Probed{reset} {green_light}>Caravaggio{reset} "#, red_light = RED_LIGHT, green_light = GREEN_LIGHT, reset = RESET, ); check_printer(write_lines, left, right, &expected); } /// Multiple deletion, single insertion - no inline diffing. #[test] fn write_lines_multiline_delete() { let left = r#"Proboscis Cabbage"#; let right = r#"Probed"#; let expected = format!( r#"{red_light}Probed{reset} "#, red_light = RED_LIGHT, green_light = GREEN_LIGHT, reset = RESET, ); check_printer(write_lines, left, right, &expected); } /// Regression test for multiline highlighting issue #[test] fn write_lines_issue12() { let left = r#"[ 0, 0, 0, 128, 10, 191, 5, 64, ]"#; let right = r#"[ 84, 248, 45, 64, ]"#; let expected = format!( r#" [ {red_light}< 0,{reset} {red_light}< 0,{reset} {red_light}< 0,{reset} {red_light}< 128,{reset} {red_light}< 10,{reset} {red_light}< 191,{reset} {red_light}< 5,{reset} {green_light}> 84,{reset} {green_light}> 248,{reset} {green_light}> 45,{reset} 64, ] "#, red_light = RED_LIGHT, green_light = GREEN_LIGHT, reset = RESET, ); check_printer(write_lines, left, right, &expected); } mod write_lines_edge_newlines { use super::*; #[test] fn both_trailing() { let left = "fan\n"; let right = "mug\n"; // Note the additional space at the bottom is caused by a trailing newline // adding an additional line with zero content to both sides of the diff let expected = format!( r#"{red_light}<{reset}{red_heavy}fan{reset} {green_light}>{reset}{green_heavy}mug{reset} "#, red_light = RED_LIGHT, red_heavy = RED_HEAVY, green_light = GREEN_LIGHT, green_heavy = GREEN_HEAVY, reset = RESET, ); check_printer(write_lines, left, right, &expected); } #[test] fn both_leading() { let left = "\nfan"; let right = "\nmug"; // Note the additional space at the top is caused by a leading newline // adding an additional line with zero content to both sides of the diff let expected = format!( r#" {red_light}<{reset}{red_heavy}fan{reset} {green_light}>{reset}{green_heavy}mug{reset} "#, red_light = RED_LIGHT, red_heavy = RED_HEAVY, green_light = GREEN_LIGHT, green_heavy = GREEN_HEAVY, reset = RESET, ); check_printer(write_lines, left, right, &expected); } #[test] fn leading_added() { let left = "fan"; let right = "\nmug"; let expected = format!( r#"{red_light}{reset} {green_light}>mug{reset} "#, red_light = RED_LIGHT, green_light = GREEN_LIGHT, reset = RESET, ); check_printer(write_lines, left, right, &expected); } #[test] fn leading_deleted() { let left = "\nfan"; let right = "mug"; let expected = format!( r#"{red_light}<{reset} {red_light}mug{reset} "#, red_light = RED_LIGHT, green_light = GREEN_LIGHT, reset = RESET, ); check_printer(write_lines, left, right, &expected); } #[test] fn trailing_added() { let left = "fan"; let right = "mug\n"; let expected = format!( r#"{red_light}mug{reset} {green_light}>{reset} "#, red_light = RED_LIGHT, green_light = GREEN_LIGHT, reset = RESET, ); check_printer(write_lines, left, right, &expected); } /// Regression test for double abort /// /// See: https://github.com/rust-pretty-assertions/rust-pretty-assertions/issues/96 #[test] fn trailing_deleted() { // The below inputs caused an abort via double panic // we panicked at 'insertion followed by deletion' let left = "fan\n"; let right = "mug"; let expected = format!( r#"{red_light}<{reset}{red_heavy}fan{reset} {green_light}>{reset}{green_heavy}mug{reset} {red_light}<{reset} "#, red_light = RED_LIGHT, red_heavy = RED_HEAVY, green_light = GREEN_LIGHT, green_heavy = GREEN_HEAVY, reset = RESET, ); check_printer(write_lines, left, right, &expected); } } } pretty_assertions-1.4.0/tests/macros.rs000064400000000000000000000215231046102023000164260ustar 00000000000000#![cfg_attr(not(feature = "std"), no_std)] #![no_implicit_prelude] #[cfg(feature = "alloc")] extern crate alloc; #[allow(clippy::eq_op)] mod assert_str_eq { use ::core::{cmp::PartialEq, convert::AsRef}; #[cfg(feature = "alloc")] use ::alloc::string::{String, ToString}; #[cfg(feature = "std")] use ::std::string::{String, ToString}; #[test] fn passes_str() { let a = "some value"; ::pretty_assertions::assert_str_eq!(a, a); } #[test] fn passes_string() { let a: String = "some value".to_string(); ::pretty_assertions::assert_str_eq!(a, a); } #[test] fn passes_comparable_types() { let s0: &'static str = "foo"; let s1: String = "foo".to_string(); ::pretty_assertions::assert_str_eq!(s0, s1); } #[derive(PartialEq)] struct MyString(String); impl AsRef for MyString { fn as_ref(&self) -> &str { &self.0 } } impl PartialEq for MyString { fn eq(&self, other: &String) -> bool { &self.0 == other } } #[test] fn passes_as_ref_types() { let s0 = MyString("foo".to_string()); let s1 = "foo".to_string(); ::pretty_assertions::assert_str_eq!(s0, s1); } #[test] #[should_panic(expected = r#"assertion failed: `(left == right)` Diff < left / right > : foo baz "#)] fn fails_as_ref_types() { let s0 = MyString("foo\nbar".to_string()); let s1 = "foo\nbaz".to_string(); ::pretty_assertions::assert_str_eq!(s0, s1); } #[test] #[should_panic(expected = r#"assertion failed: `(left == right)` Diff < left / right > : foo baz "#)] fn fails_foo() { ::pretty_assertions::assert_str_eq!("foo\nbar", "foo\nbaz"); } } #[allow(clippy::eq_op)] mod assert_eq { #[cfg(feature = "alloc")] use ::alloc::string::{String, ToString}; #[cfg(feature = "std")] use ::std::string::{String, ToString}; #[test] fn passes() { let a = "some value"; ::pretty_assertions::assert_eq!(a, a); } #[test] fn passes_unsized() { let a: &[u8] = b"e"; ::pretty_assertions::assert_eq!(*a, *a); } #[test] fn passes_comparable_types() { let s0: &'static str = "foo"; let s1: String = "foo".to_string(); ::pretty_assertions::assert_eq!(s0, s1); } #[test] #[should_panic(expected = r#"assertion failed: `(left == right)` Diff < left / right > : <666 >999 "#)] fn fails() { ::pretty_assertions::assert_eq!(666, 999); } #[test] #[should_panic(expected = r#"assertion failed: `(left == right)` Diff < left / right > : <666 >999 "#)] fn fails_trailing_comma() { ::pretty_assertions::assert_eq!(666, 999,); } #[test] #[should_panic(expected = r#"assertion failed: `(left == right)` Diff < left / right > : [ 101, > 101, ] "#)] fn fails_unsized() { let a: &[u8] = b"e"; let b: &[u8] = b"ee"; ::pretty_assertions::assert_eq!(*a, *b); } #[test] #[should_panic( expected = r#"assertion failed: `(left == right)`: custom panic message Diff < left / right > : <666 >999 "# )] fn fails_custom() { ::pretty_assertions::assert_eq!(666, 999, "custom panic message"); } #[test] #[should_panic( expected = r#"assertion failed: `(left == right)`: custom panic message Diff < left / right > : <666 >999 "# )] fn fails_custom_trailing_comma() { ::pretty_assertions::assert_eq!(666, 999, "custom panic message",); } #[test] #[should_panic(expected = r#"assertion failed: `(left == right)` Diff < left / right > : foo baz "#)] fn fails_str() { ::pretty_assertions::assert_eq!("foo\nbar", "foo\nbaz"); } #[test] #[should_panic(expected = r#"assertion failed: `(left == right)` Diff < left / right > : foo baz "#)] fn fails_string() { ::pretty_assertions::assert_eq!("foo\nbar".to_string(), "foo\nbaz".to_string()); } } mod assert_ne { #[cfg(feature = "alloc")] use ::alloc::string::{String, ToString}; #[cfg(feature = "std")] use ::std::string::{String, ToString}; #[test] fn passes() { let a = "a"; let b = "b"; ::pretty_assertions::assert_ne!(a, b); } #[test] fn passes_unsized() { let a: &[u8] = b"e"; let b: &[u8] = b"ee"; ::pretty_assertions::assert_ne!(*a, *b); } #[test] fn passes_comparable_types() { let s0: &'static str = "foo"; let s1: String = "bar".to_string(); ::pretty_assertions::assert_ne!(s0, s1); } #[test] #[should_panic(expected = r#"assertion failed: `(left != right)` Both sides: 666 "#)] fn fails() { ::pretty_assertions::assert_ne!(666, 666); } #[test] #[should_panic(expected = r#"assertion failed: `(left != right)` Both sides: 666 "#)] fn fails_trailing_comma() { ::pretty_assertions::assert_ne!(666, 666,); } #[test] #[should_panic(expected = r#"assertion failed: `(left != right)` Both sides: [ 101, ] "#)] fn fails_unsized() { let a: &[u8] = b"e"; ::pretty_assertions::assert_ne!(*a, *a); } #[test] #[should_panic( expected = r#"assertion failed: `(left != right)`: custom panic message Both sides: 666 "# )] fn fails_custom() { ::pretty_assertions::assert_ne!(666, 666, "custom panic message"); } #[test] #[should_panic( expected = r#"assertion failed: `(left != right)`: custom panic message Both sides: 666 "# )] fn fails_custom_trailing_comma() { ::pretty_assertions::assert_ne!(666, 666, "custom panic message",); } // If the values are equal but their debug outputs are not // show a specific warning // Regression tests #[test] #[should_panic] fn assert_ne_non_empty_return() { fn not_zero(x: u32) -> u32 { ::pretty_assertions::assert_ne!(x, 0); x } not_zero(0); } } #[cfg(feature = "unstable")] mod assert_matches { use ::core::option::Option::{None, Some}; #[test] fn passes() { let a = Some("some value"); ::pretty_assertions::assert_matches!(a, Some(_)); } #[test] fn passes_unsized() { let a: &[u8] = b"e"; ::pretty_assertions::assert_matches!(*a, _); } #[test] #[should_panic(expected = r#"assertion failed: `(left matches right)` Diff < left / right > : <None >Some(_) "#)] fn fails() { ::pretty_assertions::assert_matches!(None::, Some(_)); } #[test] #[should_panic(expected = r#"assertion failed: `(left matches right)` Diff < left / right > : Some(3) if 0 > 0 "#)] fn fails_guard() { ::pretty_assertions::assert_matches!(Some(3), Some(3) if 0 > 0,); } #[test] #[should_panic(expected = r#"assertion failed: `(left matches right)` Diff < left / right > : <[ < 101, <] >ref b if b == b"ee" "#)] fn fails_unsized() { let a: &[u8] = b"e"; ::pretty_assertions::assert_matches!(*a, ref b if b == b"ee"); } #[test] #[should_panic( expected = r#"assertion failed: `(left matches right)`: custom panic message Diff < left / right > : <666 >999 "# )] fn fails_custom() { ::pretty_assertions::assert_matches!(666, 999, "custom panic message"); } #[test] #[should_panic( expected = r#"assertion failed: `(left matches right)`: custom panic message Diff < left / right > : <666 >999 "# )] fn fails_custom_trailing_comma() { ::pretty_assertions::assert_matches!(666, 999, "custom panic message",); } }