diff options
author | Inna Palant <ipalant@google.com> | 2023-12-13 13:42:48 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-12-13 13:42:48 +0000 |
commit | 2ffb48c471eb53e4257c3e68c57e0047d36b1b57 (patch) | |
tree | f4196a0a7827b87fd2721945c74acffae69eeeb4 | |
parent | b3e29355fd5aaf0b15e3d0fb8c7a4433edcfb7d8 (diff) | |
parent | 431012b6b96d546160746d7b5dbcb5a2cf8788e1 (diff) | |
download | mockall-2ffb48c471eb53e4257c3e68c57e0047d36b1b57.tar.gz |
Merge remote-tracking branch 'origin/upstream' am: 2b01862e43 am: bddc41dc85 am: 431012b6b9
Original change: undetermined
Change-Id: I7baaa68e3e6d6e59b002a241d29914e2ce51fc6b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | .cargo_vcs_info.json | 6 | ||||
-rw-r--r-- | Android.bp | 29 | ||||
-rw-r--r-- | Cargo.lock | 424 | ||||
-rw-r--r-- | Cargo.toml | 109 | ||||
l--------- | LICENSE | 1 | ||||
-rw-r--r-- | LICENSE-APACHE | 201 | ||||
-rw-r--r-- | LICENSE-MIT | 25 | ||||
-rw-r--r-- | METADATA | 20 | ||||
-rw-r--r-- | MODULE_LICENSE_APACHE2 | 0 | ||||
-rw-r--r-- | OWNERS | 2 | ||||
-rw-r--r-- | README.md | 84 | ||||
-rw-r--r-- | cargo2android.json | 4 | ||||
-rw-r--r-- | src/examples.rs | 62 | ||||
-rw-r--r-- | src/lib.rs | 1699 |
14 files changed, 2666 insertions, 0 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json new file mode 100644 index 0000000..555d0e6 --- /dev/null +++ b/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "d5351f7215c6c5bca11f704ed41d9ae768b43007" + }, + "path_in_vcs": "mockall" +}
\ No newline at end of file diff --git a/Android.bp b/Android.bp new file mode 100644 index 0000000..b195dda --- /dev/null +++ b/Android.bp @@ -0,0 +1,29 @@ +// This file is generated by cargo2android.py --config cargo2android.json. +// Do not modify this file as changes will be overridden on upgrade. + + + +rust_library { + name: "libmockall", + host_supported: true, + crate_name: "mockall", + cargo_env_compat: true, + cargo_pkg_version: "0.11.4", + srcs: ["src/lib.rs"], + edition: "2018", + rustlibs: [ + "libcfg_if", + "libdowncast", + "libfragile", + "liblazy_static", + "libpredicates", + "libpredicates_tree", + ], + proc_macros: ["libmockall_derive"], + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], + product_available: true, + vendor_available: true, +} diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..d1116b2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,424 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "async-trait" +version = "0.1.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mockall" +version = "0.11.4" +dependencies = [ + "async-trait", + "cfg-if", + "downcast", + "fragile", + "futures", + "lazy_static", + "mockall_derive", + "mockall_double", + "predicates", + "predicates-tree", + "serde", + "serde_derive", + "serde_json", + "tracing", +] + +[[package]] +name = "mockall_derive" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "mockall_double" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae71c7bb287375187c775cf82e2dcf1bef3388aaf58f0789a77f9c7ab28466f6" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "predicates" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e5a7689e456ab905c22c2b48225bb921aba7c8dfa58440d68ba13f6222a715" +dependencies = [ + "difflib", + "float-cmp", + "itertools", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" + +[[package]] +name = "predicates-tree" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "proc-macro2" +version = "1.0.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "serde" +version = "1.0.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" + +[[package]] +name = "serde_derive" +version = "1.0.156" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termtree" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8b09c17 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,109 @@ +# 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" +rust-version = "1.45" +name = "mockall" +version = "0.11.4" +authors = ["Alan Somers <asomers@gmail.com>"] +exclude = [ + "examples/*", + "tests/*", + "tools/*", +] +description = """ +A powerful mock object library for Rust. +""" +documentation = "https://docs.rs/mockall" +readme = "README.md" +keywords = [ + "mock", + "mocking", + "testing", +] +categories = ["development-tools::testing"] +license = "MIT/Apache-2.0" +repository = "https://github.com/asomers/mockall" + +[package.metadata.docs.rs] +features = ["nightly"] + +[package.metadata.release] +tag-prefix = "" + +[[package.metadata.release.pre-release-replacements]] +file = "../README.md" +replace = "mockall = \"{{version}}\"" +search = 'mockall = "[a-z0-9\.-]+"' + +[[package.metadata.release.pre-release-replacements]] +file = "../CHANGELOG.md" +replace = "{{version}}" +search = "Unreleased" + +[[package.metadata.release.pre-release-replacements]] +file = "../CHANGELOG.md" +replace = "{{date}}" +search = "ReleaseDate" + +[[example]] +name = "serde" +crate-type = ["lib"] +path = "examples/serde.rs" + +[dependencies.cfg-if] +version = "1.0" + +[dependencies.downcast] +version = "0.11" + +[dependencies.fragile] +version = "2.0" + +[dependencies.lazy_static] +version = "1.1" + +[dependencies.mockall_derive] +version = "=0.11.4" + +[dependencies.predicates] +version = "2.0.1" + +[dependencies.predicates-tree] +version = "1.0" + +[dev-dependencies.async-trait] +version = "0.1.38" + +[dev-dependencies.futures] +version = "0.3.7" + +[dev-dependencies.mockall_double] +version = "^0.3.0" + +[dev-dependencies.serde] +version = "1.0" + +[dev-dependencies.serde_derive] +version = "1.0" + +[dev-dependencies.serde_json] +version = "1.0" + +[dev-dependencies.tracing] +version = "0.1.23" + +[features] +nightly = [ + "mockall_derive/nightly_derive", + "downcast/nightly", +] @@ -0,0 +1 @@ +LICENSE-APACHE
\ No newline at end of file diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..39df3da --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2019 Alan Somers + +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. diff --git a/METADATA b/METADATA new file mode 100644 index 0000000..f164e23 --- /dev/null +++ b/METADATA @@ -0,0 +1,20 @@ +name: "mockall" +description: "()" +third_party { + identifier { + type: "crates.io" + value: "https://crates.io/crates/mockall" + } + identifier { + type: "Archive" + value: "https://static.crates.io/crates/mockall/mockall-0.11.4.crate" + } + version: "0.11.4" + # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same. + license_type: NOTICE + last_upgrade_date { + year: 2023 + month: 11 + day: 6 + } +} diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/MODULE_LICENSE_APACHE2 @@ -0,0 +1,2 @@ +# Bug component: 688011 +include platform/prebuilts/rust:main:/OWNERS diff --git a/README.md b/README.md new file mode 100644 index 0000000..2bce129 --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# Mockall + +A powerful mock object library for Rust. + +[![Build Status](https://api.cirrus-ci.com/github/asomers/mockall.svg)](https://cirrus-ci.com/github/asomers/mockall) +[![Crates.io](https://img.shields.io/crates/v/mockall.svg)](https://crates.io/crates/mockall) +[![Documentation](https://docs.rs/mockall/badge.svg)](https://docs.rs/mockall) + +## Overview + +Mock objects are a powerful technique for unit testing software. A mock object +is an object with the same interface as a real object, but whose responses are +all manually controlled by test code. They can be used to test the upper and +middle layers of an application without instantiating the lower ones, or to +inject edge and error cases that would be difficult or impossible to create +when using the full stack. + +Statically typed languages are inherently more difficult to +mock than dynamically typed languages. Since Rust is a statically typed language, +previous attempts at creating a mock object library have had mixed results. Mockall +incorporates the best elements of previous designs, resulting in it having a rich +feature set with a terse and ergonomic interface. Mockall is written in 100% *safe* +and *stable* Rust. + +## Usage + +Typically mockall is only used by unit tests. To use it this way, add this to +your `Cargo.toml`: + +```toml +[dev-dependencies] +mockall = "0.11.4" +``` + +Then use it like this: + +```rust +#[cfg(test)] +use mockall::{automock, mock, predicate::*}; +#[cfg_attr(test, automock)] +trait MyTrait { + fn foo(&self, x: u32) -> u32; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn mytest() { + let mut mock = MockMyTrait::new(); + mock.expect_foo() + .with(eq(4)) + .times(1) + .returning(|x| x + 1); + assert_eq!(5, mock.foo(4)); + } +} +``` + +See the [API docs](https://docs.rs/mockall) for more information. + +# Minimum Supported Rust Version (MSRV) + +Mockall is supported on Rust 1.42.0 and higher. Mockall's MSRV will not be +changed in the future without bumping the major or minor version. + +# License + +`mockall` is primarily distributed under the terms of both the MIT license +and the Apache License (Version 2.0). + +See LICENSE-APACHE, and LICENSE-MIT for details + +# Acknowledgements + +Mockall was not built in a day. JMock was probably the first popular mock +object library. Many ports and imitations have been made, including GoogleMock +for C++. Mockers, inspired by GoogleMock, was the first attempt to bring the +concept to Rust. The now-defunct Mock_derive was the first library to generate +mock objects with procedural macros, greatly reducing the user's workload. +Mockall also uses proc macros, and copies many of Mockers' features and +conventions. Mockall also takes inspiration from Simulacrum's internal design, +and its technique for mocking generic methods. diff --git a/cargo2android.json b/cargo2android.json new file mode 100644 index 0000000..bf78496 --- /dev/null +++ b/cargo2android.json @@ -0,0 +1,4 @@ +{ + "device": true, + "run": true +}
\ No newline at end of file diff --git a/src/examples.rs b/src/examples.rs new file mode 100644 index 0000000..a630752 --- /dev/null +++ b/src/examples.rs @@ -0,0 +1,62 @@ +// vim: tw=80 +//! Examples of Mockall's generated code +use mockall::{mock, automock}; + +/// Mock of a basic trait with several kinds of method. +/// +/// It is mocked by the [`MockFoo`](struct.MockFoo.html) struct. +#[automock] +pub trait Foo { + /// A method with a `'static` return type + fn foo(&self, x: i32, y: i16) -> i32; + + /// A method returning a reference + fn bar(&self, x: i32) -> &i32; + + /// A method returning a mutable reference + fn baz(&mut self, x: i32) -> &mut i32; + + /// A method returning a `'static` reference + fn bean(&self) -> &'static i32; + + /// A static method + fn bang(x: i32) -> i32; +} + +/// A trait implemented by a Struct we want to mock +pub trait Bah { + /// Some trait method + fn bah(&self); +} + +mock! { + /// Mock of a struct + /// + /// Structs can be mocked with [`mock!`]. + /// Their mock methods have an identical API to the methods generated by + /// [`#[automock]`](automock). + pub Boo { + /// A method on a struct + fn boo(&self); + } + /// An implementation of a trait on a mocked struct + trait Bah { + fn bah(&self); + } +} + +#[automock(mod mock_ffi;)] +extern "C" { + /// A foreign "C" function. + pub fn ffi_func(); +} + +#[cfg(feature = "nightly")] +/// Mock this entire module +#[automock] +pub mod my_module { + /// A function in a mocked module + pub fn modfunc() { + unimplemented!() + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..121fff3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,1699 @@ +// vim: tw=80 +//! A powerful mock object library for Rust. +//! +//! Mockall provides tools to create mock versions of almost any trait +//! or struct. They can be used in unit tests as a stand-in for the real +//! object. +//! +//! # Usage +//! +//! There are two ways to use Mockall. The easiest is to use +//! [`#[automock]`](attr.automock.html). It can mock most traits, or structs +//! that only have a single `impl` block. For things it can't handle, there is +//! [`mock!`]. +//! +//! Whichever method is used, the basic idea is the same. +//! * Create a mock struct. It's name will be the same as the original, with +//! "Mock" prepended. +//! * In your test, instantiate the mock struct with its `new` or `default` +//! method. +//! * Set expectations on the mock struct. Each expectation can have required +//! argument matchers, a required call count, and a required position in a +//! [`Sequence`]. Each expectation must also have a return value. +//! * Supply the mock object to the code that you're testing. It will return +//! the preprogrammed return values supplied in the previous step. Any +//! accesses contrary to your expectations will cause a panic. +//! +//! # User Guide +//! +//! * [`Getting started`](#getting-started) +//! * [`Static Return values`](#static-return-values) +//! * [`Matching arguments`](#matching-arguments) +//! * [`Call counts`](#call-counts) +//! * [`Sequences`](#sequences) +//! * [`Checkpoints`](#checkpoints) +//! * [`Reference arguments`](#reference-arguments) +//! * [`Reference return values`](#reference-return-values) +//! * [`impl Trait`](#impl-trait) +//! * [`Mocking structs`](#mocking-structs) +//! * [`Generic methods`](#generic-methods) +//! * [`Methods with generic lifetimes`](#methods-with-generic-lifetimes) +//! * [`Generic traits and structs`](#generic-traits-and-structs) +//! * [`Associated types`](#associated-types) +//! * [`Multiple and inherited traits`](#multiple-and-inherited-traits) +//! * [`External traits`](#external-traits) +//! * [`Static methods`](#static-methods) +//! * [`Modules`](#modules) +//! * [`Foreign functions`](#foreign-functions) +//! * [`Debug`](#debug) +//! * [`Async Traits`](#async-traits) +//! * [`Crate features`](#crate-features) +//! * [`Examples`](#examples) +//! +//! ## Getting Started +//! ``` +//! use mockall::*; +//! use mockall::predicate::*; +//! #[automock] +//! trait MyTrait { +//! fn foo(&self, x: u32) -> u32; +//! } +//! +//! fn call_with_four(x: &MyTrait) -> u32 { +//! x.foo(4) +//! } +//! +//! let mut mock = MockMyTrait::new(); +//! mock.expect_foo() +//! .with(predicate::eq(4)) +//! .times(1) +//! .returning(|x| x + 1); +//! assert_eq!(5, call_with_four(&mock)); +//! ``` +//! +//! ## Static Return values +//! +//! Every expectation must have an associated return value (though when the +//! **nightly** feature is enabled expectations will automatically return the +//! default values of their return types, if their return types implement +//! `Default`.). For methods that return a `static` value, the macros will +//! generate an `Expectation` struct like +//! [`this`](examples::__mock_MockFoo_Foo::__foo::Expectation). +//! There are two ways to set such an expectation's return value: with a +//! constant +//! ([`return_const`](examples::__mock_MockFoo_Foo::__foo::Expectation::return_const)) +//! or a closure +//! ([`returning`](examples::__mock_MockFoo_Foo::__foo::Expectation::returning)). +//! A closure will take the method's arguments by value. +//! +//! ``` +//! # use mockall::*; +//! #[automock] +//! trait MyTrait { +//! fn foo(&self) -> u32; +//! fn bar(&self, x: u32, y: u32) -> u32; +//! } +//! +//! let mut mock = MockMyTrait::new(); +//! mock.expect_foo() +//! .return_const(42u32); +//! mock.expect_bar() +//! .returning(|x, y| x + y); +//! ``` +//! +//! Additionally, constants that aren't `Clone` can be returned with the +//! [`return_once`](examples::__mock_MockFoo_Foo::__foo::Expectation::return_once) +//! method. +//! +//! ``` +//! # use mockall::*; +//! struct NonClone(); +//! #[automock] +//! trait Foo { +//! fn foo(&self) -> NonClone; +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! let r = NonClone{}; +//! mock.expect_foo() +//! .return_once(move || r); +//! # } +//! ``` +//! +//! `return_once` can also be used for computing the return value with an +//! `FnOnce` closure. This is useful for returning a non-`Clone` value and also +//! triggering side effects at the same time. +//! +//! ``` +//! # use mockall::*; +//! fn do_something() {} +//! +//! struct NonClone(); +//! +//! #[automock] +//! trait Foo { +//! fn foo(&self) -> NonClone; +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! let r = NonClone{}; +//! mock.expect_foo() +//! .return_once(move || { +//! do_something(); +//! r +//! }); +//! # } +//! ``` +//! +//! Mock objects are always `Send`. If you need to use a return type that +//! isn't, you can use the +//! [`return_const_st`](examples::__mock_MockFoo_Foo::__foo::Expectation::return_const_st), +//! [`returning_st`](examples::__mock_MockFoo_Foo::__foo::Expectation::returning_st), +//! or +//! [`return_once_st`](examples::__mock_MockFoo_Foo::__foo::Expectation::return_once_st), +//! methods. If you need to match arguments that are not `Send`, you can use the +//! [`withf_st`](examples::__mock_MockFoo_Foo::__foo::Expectation::withf_st) +//! These take a non-`Send` object and add runtime access checks. The wrapped +//! object will be `Send`, but accessing it from multiple threads will cause a +//! runtime panic. +//! +//! ``` +//! # use mockall::*; +//! # use std::rc::Rc; +//! #[automock] +//! trait Foo { +//! fn foo(&self, x: Rc<u32>) -> Rc<u32>; // Rc<u32> isn't Send +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! let x = Rc::new(5); +//! let argument = x.clone(); +//! mock.expect_foo() +//! .withf_st(move |x| *x == argument) +//! .returning_st(move |_| Rc::new(42u32)); +//! assert_eq!(42, *mock.foo(x)); +//! # } +//! ``` +//! +//! ## Matching arguments +//! +//! Optionally, expectations may have argument matchers set. A matcher will +//! verify that the expectation was called with the expected arguments, or panic +//! otherwise. A matcher is anything that implements the [`Predicate`] trait. +//! For example: +//! +//! ```should_panic +//! # use mockall::*; +//! # use mockall::predicate::*; +//! #[automock] +//! trait Foo { +//! fn foo(&self, x: u32); +//! } +//! +//! let mut mock = MockFoo::new(); +//! mock.expect_foo() +//! .with(eq(42)) +//! .return_const(()); +//! +//! mock.foo(0); // Panics! +//! ``` +//! +//! See [`predicate`] for a list of Mockall's builtin predicate functions. +//! For convenience, +//! [`withf`](examples::__mock_MockFoo_Foo::__foo::Expectation::withf) +//! is a shorthand for setting the commonly used +//! [`function`] predicate. The arguments to the predicate function are the +//! method's arguments, *by reference*. For example: +//! +//! ```should_panic +//! # use mockall::*; +//! #[automock] +//! trait Foo { +//! fn foo(&self, x: u32, y: u32); +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! mock.expect_foo() +//! .withf(|x: &u32, y: &u32| x == y) +//! .return_const(()); +//! +//! mock.foo(2 + 2, 5); // Panics! +//! # } +//! ``` +//! +//! ### Matching multiple calls +//! +//! Matchers can also be used to discriminate between different invocations of +//! the same function. Used that way, they can provide different return values +//! for different arguments. The way this works is that on a method call, all +//! expectations set on a given method are evaluated in FIFO order. The first +//! matching expectation is used. Only if none of the expectations match does +//! Mockall panic. For example: +//! +//! ``` +//! # use mockall::*; +//! # use mockall::predicate::*; +//! #[automock] +//! trait Foo { +//! fn foo(&self, x: u32) -> u32; +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! mock.expect_foo() +//! .with(eq(5)) +//! .return_const(50u32); +//! mock.expect_foo() +//! .with(eq(6)) +//! .return_const(60u32); +//! # } +//! ``` +//! +//! One common pattern is to use multiple expectations in order of decreasing +//! specificity. The last expectation can provide a default or fallback value, +//! and earlier ones can be more specific. For example: +//! +//! ``` +//! # use mockall::*; +//! # use mockall::predicate::*; +//! #[automock] +//! trait Foo { +//! fn open(&self, path: String) -> Option<u32>; +//! } +//! +//! let mut mock = MockFoo::new(); +//! mock.expect_open() +//! .with(eq(String::from("something.txt"))) +//! .returning(|_| Some(5)); +//! mock.expect_open() +//! .return_const(None); +//! ``` +//! +//! ## Call counts +//! +//! By default, every expectation is allowed to be called an unlimited number of +//! times. But Mockall can optionally verify that an expectation was called a +//! fixed number of times, or any number of times within a given range. +//! +//! ```should_panic +//! # use mockall::*; +//! # use mockall::predicate::*; +//! #[automock] +//! trait Foo { +//! fn foo(&self, x: u32); +//! } +//! +//! let mut mock = MockFoo::new(); +//! mock.expect_foo() +//! .times(1) +//! .return_const(()); +//! +//! mock.foo(0); // Ok +//! mock.foo(1); // Panics! +//! ``` +//! +//! See also +//! [`never`](examples::__mock_MockFoo_Foo::__foo::Expectation::never) and +//! [`times`](examples::__mock_MockFoo_Foo::__foo::Expectation::times). +//! +//! ## Sequences +//! +//! By default expectations may be matched in any order. But it's possible to +//! specify the order by using a [`Sequence`]. Any expectations may be added to +//! the same sequence. They don't even need to come from the same object. +//! +//! ```should_panic(expected = "Method sequence violation") +//! # use mockall::*; +//! #[automock] +//! trait Foo { +//! fn foo(&self); +//! } +//! +//! # fn main() { +//! let mut seq = Sequence::new(); +//! +//! let mut mock1 = MockFoo::new(); +//! mock1.expect_foo() +//! .times(1) +//! .in_sequence(&mut seq) +//! .returning(|| ()); +//! +//! let mut mock2 = MockFoo::new(); +//! mock2.expect_foo() +//! .times(1) +//! .in_sequence(&mut seq) +//! .returning(|| ()); +//! +//! mock2.foo(); // Panics! mock1.foo should've been called first. +//! # } +//! ``` +//! +//! ## Checkpoints +//! +//! Sometimes its useful to validate all expectations mid-test, throw them away, +//! and add new ones. That's what checkpoints do. Every mock object has a +//! `checkpoint` method. When called, it will immediately validate all methods' +//! expectations. So any expectations that haven't satisfied their call count +//! will panic. Afterwards, those expectations will be cleared so you can add +//! new expectations and keep testing. +//! +//! ```should_panic +//! # use mockall::*; +//! #[automock] +//! trait Foo { +//! fn foo(&self); +//! } +//! +//! let mut mock = MockFoo::new(); +//! mock.expect_foo() +//! .times(2) +//! .returning(|| ()); +//! +//! mock.foo(); +//! mock.checkpoint(); // Panics! foo hasn't yet been called twice. +//! ``` +//! +//! ```should_panic +//! # use mockall::*; +//! #[automock] +//! trait Foo { +//! fn foo(&self); +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! mock.expect_foo() +//! .times(1) +//! .returning(|| ()); +//! +//! mock.foo(); +//! mock.checkpoint(); +//! mock.foo(); // Panics! The expectation has been cleared. +//! # } +//! ``` +//! +//! ## Reference arguments +//! +//! Mockall can mock methods with reference arguments, too. There's one catch: +//! the matcher [`Predicate`] will take reference arguments by value, not by +//! reference. +//! +//! ``` +//! # use mockall::*; +//! #[automock] +//! trait Foo { +//! fn foo(&self, x: &u32) -> u32; +//! } +//! +//! let mut mock = MockFoo::new(); +//! let e = mock.expect_foo() +//! // Note that x is a &u32, not a &&u32 +//! .withf(|x: &u32| *x == 5) +//! .returning(|x: &u32| *x + 1); +//! +//! assert_eq!(6, mock.foo(&5)); +//! ``` +//! +//! ## Reference return values +//! +//! Mockall can also use reference return values. There is one restriction: the +//! lifetime of the returned reference must be either the same as the lifetime +//! of the mock object, or `'static`. +//! +//! Mockall creates different expectation types for methods that return +//! references. Their API is the same as the basic `Expectation`, except for +//! setting return values. +//! +//! Methods that return `'static` references work just like methods that return +//! any other `'static` value. +//! ``` +//! # use mockall::*; +//! struct Thing(u32); +//! +//! #[automock] +//! trait Container { +//! fn get(&self, i: u32) -> &'static Thing; +//! } +//! +//! # fn main() { +//! const THING: Thing = Thing(42); +//! let mut mock = MockContainer::new(); +//! mock.expect_get() +//! .return_const(&THING); +//! +//! assert_eq!(42, mock.get(0).0); +//! # } +//! ``` +//! +//! Methods that take a `&self` argument use an `Expectation` class like +//! [this](examples::__mock_MockFoo_Foo::__bar::Expectation), +//! which +//! gets its return value from the +//! [`return_const`](examples::__mock_MockFoo_Foo::__bar::Expectation::return_const) method. +//! +//! ``` +//! # use mockall::*; +//! struct Thing(u32); +//! +//! #[automock] +//! trait Container { +//! fn get(&self, i: u32) -> &Thing; +//! } +//! +//! # fn main() { +//! let thing = Thing(42); +//! let mut mock = MockContainer::new(); +//! mock.expect_get() +//! .return_const(thing); +//! +//! assert_eq!(42, mock.get(0).0); +//! # } +//! ``` +//! +//! Methods that take a `&mut self` argument use an `Expectation` class like +//! [this](examples::__mock_MockFoo_Foo::__baz::Expectation), +//! class, regardless of whether the return value is actually mutable. They can +//! take their return value either from the +//! [`return_var`](examples::__mock_MockFoo_Foo::__baz::Expectation::return_var) +//! or +//! [`returning`](examples::__mock_MockFoo_Foo::__baz::Expectation::returning) +//! methods. +//! +//! ``` +//! # use mockall::*; +//! struct Thing(u32); +//! +//! #[automock] +//! trait Container { +//! fn get_mut(&mut self, i: u32) -> &mut Thing; +//! } +//! +//! # fn main() { +//! let thing = Thing(42); +//! let mut mock = MockContainer::new(); +//! mock.expect_get_mut() +//! .return_var(thing); +//! +//! mock.get_mut(0).0 = 43; +//! assert_eq!(43, mock.get_mut(0).0); +//! # } +//! ``` +//! +//! Unsized types that are common targets for +//! [`Deref`](core::ops::Deref) +//! are special. Mockall +//! will automatically use the type's owned form for the Expectation. +//! Currently, the +//! [`CStr`](std::ffi::CStr), +//! [`OsStr`](std::ffi::OsStr), +//! [`Path`](std::path::Path), +//! [`Slice`][std::slice], +//! and +//! [`str`](std::str) +//! types are supported. Using this feature is automatic: +//! +//! ``` +//! # use mockall::*; +//! #[automock] +//! trait Foo { +//! fn name(&self) -> &str; +//! } +//! +//! let mut mock = MockFoo::new(); +//! mock.expect_name().return_const("abcd".to_owned()); +//! assert_eq!("abcd", mock.name()); +//! ``` +//! +//! Similarly, Mockall will use a Boxed trait object for the Expectation of +//! methods that return references to trait objects. +//! +//! ``` +//! # use mockall::*; +//! # use std::fmt::Display; +//! #[automock] +//! trait Foo { +//! fn name(&self) -> &dyn Display; +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! mock.expect_name().return_const(Box::new("abcd")); +//! assert_eq!("abcd", format!("{}", mock.name())); +//! # } +//! ``` +//! +//! +//! ## Impl Trait +//! +//! Rust 1.26.0 introduced the `impl Trait` feature. It allows functions to +//! return concrete but unnamed types (and, less usefully, to take them as +//! arguments). It's *almost* the same as `Box<dyn Trait>` but without the +//! extra allocation. Mockall supports deriving mocks for methods that return +//! `impl Trait`, with limitations. When you derive the mock for such a method, +//! Mockall internally transforms the Expectation's return type to `Box<dyn +//! Trait>`, without changing the mock method's signature. So you can use it +//! like this: +//! +//! ``` +//! # use mockall::*; +//! # use std::fmt::Debug; +//! struct Foo {} +//! #[automock] +//! impl Foo { +//! fn foo(&self) -> impl Debug { +//! // ... +//! # 4 +//! } +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! mock.expect_foo() +//! .returning(|| Box::new(String::from("Hello, World!"))); +//! println!("{:?}", mock.foo()); +//! # } +//! ``` +//! +//! However, `impl Trait` isn't *exactly* equivalent to `Box<dyn Trait>` but +//! with fewer allocations. There are some things the former can do but the +//! latter can't. For one thing, you can't build a trait object out of a +//! `Sized` trait. So this won't work: +//! +//! ```compile_fail +//! # use mockall::*; +//! struct Foo {} +//! #[automock] +//! impl Foo { +//! fn foo(&self) -> impl Clone { +//! // ... +//! # 4 +//! } +//! } +//! ``` +//! +//! Nor can you create a trait object that implements two or more non-auto +//! types. So this won't work either: +//! +//! ```compile_fail +//! # use mockall::*; +//! struct Foo {} +//! #[automock] +//! impl Foo { +//! fn foo(&self) -> impl Debug + Display { +//! // ... +//! # 4 +//! } +//! } +//! ``` +//! +//! For such cases, there is no magic bullet. The best way to mock methods like +//! those would be to refactor them to return named (but possibly opaque) types +//! instead. +//! +//! See Also [`impl-trait-for-returning-complex-types-with-ease.html`](https://rust-lang-nursery.github.io/edition-guide/rust-2018/trait-system/impl-trait-for-returning-complex-types-with-ease) +//! +//! ### impl Future +//! +//! Rust 1.36.0 added the `Future` trait. Unlike virtually every trait that +//! preceeded it, `Box<dyn Future>` is mostly useless. Instead, you usually +//! need a `Pin<Box<dyn Future>>`. So that's what Mockall will do when you mock +//! a method returning `impl Future` or the related `impl Stream`. Just +//! remember to use `pin` in your expectations, like this: +//! +//! ``` +//! # use mockall::*; +//! # use std::fmt::Debug; +//! # use futures::{Future, future}; +//! struct Foo {} +//! #[automock] +//! impl Foo { +//! fn foo(&self) -> impl Future<Output=i32> { +//! // ... +//! # future::ready(42) +//! } +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! mock.expect_foo() +//! .returning(|| Box::pin(future::ready(42))); +//! # } +//! ``` +//! +//! ## Mocking structs +//! +//! Mockall mocks structs as well as traits. The problem here is a namespace +//! problem: it's hard to supply the mock object to your code under test, +//! because it has a different name. The solution is to alter import paths +//! during test. The easiest way to do that is with the +//! [`mockall_double`](https://docs.rs/mockall_double/latest) crate. +//! +//! [`#[automock]`](attr.automock.html) +//! works for structs that have a single `impl` block: +//! ```no_run +//! use mockall_double::double; +//! mod thing { +//! use mockall::automock; +//! pub struct Thing{} +//! #[automock] +//! impl Thing { +//! pub fn foo(&self) -> u32 { +//! // ... +//! # unimplemented!() +//! } +//! } +//! } +//! +//! #[double] +//! use thing::Thing; +//! +//! fn do_stuff(thing: &Thing) -> u32 { +//! thing.foo() +//! } +//! +//! #[cfg(test)] +//! mod t { +//! use super::*; +//! +//! #[test] +//! fn test_foo() { +//! let mut mock = Thing::default(); +//! mock.expect_foo().returning(|| 42); +//! do_stuff(&mock); +//! } +//! } +//! # fn main() {} +//! ``` +//! For structs with more than one `impl` block or that have unsupported +//! `#[derive(X)]` attributes, e.g. `Clone`, see [`mock!`] instead. +//! +//! ## Generic methods +//! +//! Generic methods can be mocked, too. Effectively each generic method is an +//! infinite set of regular methods, and each of those works just like any other +//! regular method. The expect_* method is generic, too, and usually must be +//! called with a turbofish. The only restrictions on mocking generic methods +//! are that all generic parameters must be `'static`, and generic lifetime +//! parameters are not allowed. +//! +//! ``` +//! # use mockall::*; +//! #[automock] +//! trait Foo { +//! fn foo<T: 'static>(&self, t: T) -> i32; +//! } +//! +//! let mut mock = MockFoo::new(); +//! mock.expect_foo::<i16>() +//! .returning(|t| i32::from(t)); +//! mock.expect_foo::<i8>() +//! .returning(|t| -i32::from(t)); +//! +//! assert_eq!(5, mock.foo(5i16)); +//! assert_eq!(-5, mock.foo(5i8)); +//! ``` +//! +//! ## Methods with generic lifetimes +//! +//! A method with a lifetime parameter is technically a generic method, but +//! Mockall treats it like a non-generic method that must work for all possible +//! lifetimes. Mocking such a method is similar to mocking a non-generic +//! method, with a few additional restrictions. One restriction is that you +//! can't match calls with `with`, you must use `withf` instead. Another is +//! that the generic lifetime may not appear as part of the return type. +//! Finally, no method may have both generic lifetime parameters *and* generic +//! type parameters. +//! +//! ``` +//! # use mockall::*; +//! struct X<'a>(&'a i32); +//! +//! #[automock] +//! trait Foo { +//! fn foo<'a>(&self, x: X<'a>) -> i32; +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::new(); +//! mock.expect_foo() +//! .withf(|f| *f.0 == 5) +//! .return_const(42); +//! let x = X(&5); +//! assert_eq!(42, mock.foo(x)); +//! # } +//! ``` +//! +//! ## Generic traits and structs +//! +//! Mocking generic structs and generic traits is not a problem. The mock +//! struct will be generic, too. The same restrictions apply as with mocking +//! generic methods: each generic parameter must be `'static`, and generic +//! lifetime parameters are not allowed. +//! +//! ``` +//! # use mockall::*; +//! #[automock] +//! trait Foo<T: 'static> { +//! fn foo(&self, t: T) -> i32; +//! } +//! +//! # fn main() { +//! let mut mock = MockFoo::<i16>::new(); +//! mock.expect_foo() +//! .returning(|t| i32::from(t)); +//! assert_eq!(5, mock.foo(5i16)); +//! # } +//! ``` +//! +//! ## Associated types +//! +//! Traits with associated types can be mocked too. Unlike generic traits, the +//! mock struct will not be generic. Instead, you must specify the associated +//! types when defining the mock struct. They're specified as metaitems to the +//! [`#[automock]`](attr.automock.html) attribute. +//! +//! ``` +//! # use mockall::*; +//! #[automock(type Key=u16; type Value=i32;)] +//! pub trait A { +//! type Key; +//! type Value; +//! fn foo(&self, k: Self::Key) -> Self::Value; +//! } +//! +//! let mut mock = MockA::new(); +//! mock.expect_foo() +//! .returning(|x: u16| i32::from(x)); +//! assert_eq!(4, mock.foo(4)); +//! ``` +//! +//! ## Multiple and inherited traits +//! +//! Creating a mock struct that implements multiple traits, whether inherited or +//! not, requires using the [`mock!`] macro. But once created, +//! using it is just the same as using any other mock object: +//! +//! ``` +//! # use mockall::*; +//! pub trait A { +//! fn foo(&self); +//! } +//! +//! pub trait B: A { +//! fn bar(&self); +//! } +//! +//! mock! { +//! // Structure to mock +//! C {} +//! // First trait to implement on C +//! impl A for C { +//! fn foo(&self); +//! } +//! // Second trait to implement on C +//! impl B for C { +//! fn bar(&self); +//! } +//! } +//! # fn main() { +//! let mut mock = MockC::new(); +//! mock.expect_foo().returning(|| ()); +//! mock.expect_bar().returning(|| ()); +//! mock.foo(); +//! mock.bar(); +//! # } +//! ``` +//! +//! ## External traits +//! +//! Mockall can mock traits and structs defined in external crates that are +//! beyond your control, but you must use [`mock!`] instead of +//! [`#[automock]`](attr.automock.html). Mock an external trait like this: +//! +//! ``` +//! # use mockall::*; +//! mock! { +//! MyStruct {} // Name of the mock struct, less the "Mock" prefix +//! impl Clone for MyStruct { // specification of the trait to mock +//! fn clone(&self) -> Self; +//! } +//! } +//! +//! # fn main() { +//! let mut mock1 = MockMyStruct::new(); +//! let mock2 = MockMyStruct::new(); +//! mock1.expect_clone() +//! .return_once(move || mock2); +//! let cloned = mock1.clone(); +//! # } +//! ``` +//! +//! ## Static methods +//! +//! Mockall can also mock static methods. But be careful! The expectations are +//! global. If you want to use a static method in multiple tests, you must +//! provide your own synchronization. See the [`synchronization +//! example`](https://github.com/asomers/mockall/blob/master/mockall/examples/synchronization.rs) +//! for a basic implementation. For ordinary methods, expectations are +//! set on the mock object. But static methods don't have any mock object. +//! Instead, you must create a `Context` object just to set their expectations. +//! +//! ``` +//! # use mockall::*; +//! #[automock] +//! pub trait A { +//! fn foo() -> u32; +//! } +//! +//! let ctx = MockA::foo_context(); +//! ctx.expect().returning(|| 99); +//! assert_eq!(99, MockA::foo()); +//! ``` +//! +//! A common pattern is mocking a trait with a constructor method. In this case, +//! you can easily set the mock constructor method to return a mock object. +//! +//! ``` +//! # use mockall::*; +//! struct Foo{} +//! #[automock] +//! impl Foo { +//! fn from_i32(x: i32) -> Self { +//! // ... +//! # unimplemented!() +//! } +//! fn foo(&self) -> i32 { +//! // ... +//! # unimplemented!() +//! } +//! } +//! +//! # fn main() { +//! let ctx = MockFoo::from_i32_context(); +//! ctx.expect() +//! .returning(|x| { +//! let mut mock = MockFoo::default(); +//! mock.expect_foo() +//! .return_const(x); +//! mock +//! }); +//! let foo = MockFoo::from_i32(42); +//! assert_eq!(42, foo.foo()); +//! # } +//! ``` +//! +//! ### Generic static methods +//! +//! Mocking static methods of generic structs or traits, whether or not the +//! methods themselves are generic, should work seamlessly. +//! +//! ``` +//! # use mockall::*; +//! #[automock] +//! trait Foo<T: 'static> { +//! fn new(t: T) -> MockFoo<T>; +//! } +//! +//! # fn main() { +//! let ctx = MockFoo::<u32>::new_context(); +//! ctx.expect() +//! .returning(|_| MockFoo::default()); +//! let mock = MockFoo::<u32>::new(42u32); +//! # } +//! ``` +//! +//! ### Context checkpoints +//! +//! The context object cleans up all expectations when it leaves scope. It also +//! has a `checkpoint` method that functions just like a mock object's +//! `checkpoint` method. +//! +//! ```should_panic +//! # use mockall::*; +//! #[automock] +//! pub trait A { +//! fn foo() -> u32; +//! } +//! +//! let ctx = MockA::foo_context(); +//! ctx.expect() +//! .times(1) +//! .returning(|| 99); +//! ctx.checkpoint(); // Panics! +//! ``` +//! +//! A mock object's checkpoint method does *not* checkpoint static methods. +//! This behavior is useful when using multiple mock objects at once. For +//! example: +//! +//! ``` +//! # use mockall::*; +//! #[automock] +//! pub trait A { +//! fn build() -> Self; +//! fn bar(&self) -> i32; +//! } +//! +//! # fn main() { +//! let ctx = MockA::build_context(); +//! ctx.expect() +//! .times(2) +//! .returning(|| MockA::default()); +//! let mut mock0 = MockA::build(); +//! mock0.expect_bar().return_const(4); +//! mock0.bar(); +//! mock0.checkpoint(); // Does not checkpoint the build method +//! let mock1 = MockA::build(); +//! # } +//! ``` +//! +//! One more thing: Mockall normally creates a zero-argument `new` method for +//! every mock struct. But it *won't* do that when mocking a struct that +//! already has a method named `new`. The `default` method will still be +//! present. +//! +//! ## Modules +//! +//! In addition to mocking types, Mockall can also derive mocks for +//! entire modules of Rust functions. Mockall will generate a new module named +//! "mock_xxx", if "xxx" is the original module's name. You can also use +//! `#[double]` to selectively import the mock module. +//! +//! Be careful! Module functions are static and so have the same caveats as +//! [static methods](#static-methods) described above. +//! +//! ``` +//! # use mockall::*; +//! # use mockall_double::*; +//! mod outer { +//! use mockall::automock; +//! #[automock()] +//! pub(super) mod inner { +//! pub fn bar(x: u32) -> i64 { +//! // ... +//! # 4 +//! } +//! } +//! } +//! +//! #[double] +//! use outer::inner; +//! +//! #[cfg(test)] +//! mod t { +//! use super::*; +//! +//! #[test] +//! fn test_foo_bar() { +//! let ctx = inner::bar_context(); +//! ctx.expect() +//! .returning(|x| i64::from(x + 1)); +//! assert_eq!(5, inner::bar(4)); +//! } +//! } +//! # fn main() {} +//! ``` +//! +//! ### Foreign functions +//! +//! One reason to mock modules is when working with foreign functions. Modules +//! may contain foreign functions, even though structs and traits may not. Like +//! static methods, the expectations are global. +//! +//! ``` +//! # use mockall_double::*; +//! mod outer { +//! # use mockall::*; +//! #[automock] +//! pub mod ffi { +//! extern "C" { +//! pub fn foo(x: u32) -> i64; +//! } +//! } +//! } +//! +//! #[double] +//! use outer::ffi; +//! +//! fn do_stuff() -> i64 { +//! unsafe{ ffi::foo(42) } +//! } +//! +//! #[cfg(test)] +//! mod t { +//! use super::*; +//! +//! #[test] +//! fn test_foo() { +//! let ctx = ffi::foo_context(); +//! ctx.expect() +//! .returning(|x| i64::from(x + 1)); +//! assert_eq!(43, do_stuff()); +//! } +//! } +//! # fn main() {} +//! ``` +//! +//! ## Debug +//! +//! `#[automock]` will automatically generate `Debug` impls when mocking traits +//! and struct impls. `mock!` will too, if you add a `#[derive(Debug)]`, like +//! this: +//! ```no_run +//! # use mockall::*; +//! mock! { +//! #[derive(Debug)] +//! pub Foo {} +//! } +//! # fn main() { +//! # format!("{:?}", &MockFoo::default()); +//! # } +//! ``` +//! +//! ## Async Traits +//! +//! Async traits aren't yet (as of 1.47.0) a part of the Rust language. But +//! they're available from the +//! [`async_trait`](https://docs.rs/async-trait/0.1.38/async_trait/) crate. +//! Mockall is compatible with this crate, with two important limitations: +//! +//! * The `#[automock]` attribute must appear _before_ the `#[async_trait]` +//! attribute. +//! +//! * The `#[async_trait]` macro must be imported with its canonical name. +//! +//! ``` +//! # use async_trait::async_trait; +//! # use mockall::*; +//! // async_trait works with both #[automock] +//! #[automock] +//! #[async_trait] +//! pub trait Foo { +//! async fn foo(&self) -> u32; +//! } +//! // and mock! +//! mock! { +//! pub Bar {} +//! #[async_trait] +//! impl Foo for Bar { +//! async fn foo(&self) -> u32; +//! } +//! } +//! # fn main() {} +//! ``` +//! +//! ## Crate features +//! +//! Mockall has a **nightly** feature. Currently this feature has two +//! effects: +//! +//! * The compiler will produce better error messages. +//! +//! * Expectations for methods whose return type implements `Default` needn't +//! have their return values explicitly set. Instead, they will automatically +//! return the default value. +//! +//! With **nightly** enabled, you can omit the return value like this: +#![cfg_attr(feature = "nightly", doc = "```")] +#![cfg_attr(not(feature = "nightly"), doc = "```should_panic")] +//! # use mockall::*; +//! #[automock] +//! trait Foo { +//! fn foo(&self) -> Vec<u32>; +//! } +//! +//! let mut mock = MockFoo::new(); +//! mock.expect_foo(); +//! assert!(mock.foo().is_empty()); +//! ``` +//! +//! ## Examples +//! +//! For additional examples of Mockall in action, including detailed +//! documentation on the autogenerated methods, see +//! [`examples`](examples). +//! +//! [`Predicate`]: trait.Predicate.html +//! [`Sequence`]: Sequence +//! [`cfg-if`]: https://crates.io/crates/cfg-if +//! [`function`]: predicate/fn.function.html +//! [`mock!`]: macro.mock.html +//! [`predicate`]: predicate/index.html + +#![cfg_attr(feature = "nightly", feature(specialization))] +// Allow the incomplete_feature warning for specialization. We know it's +// incomplete; that's why it's guarded by the "nightly" feature. +#![cfg_attr(feature = "nightly", allow(incomplete_features))] + +#![cfg_attr(feature = "nightly", feature(doc_cfg))] +#![cfg_attr(test, deny(warnings))] +#![warn(missing_docs)] + +use downcast::*; +use std::{ + any, + fmt::{self, Debug, Formatter}, + marker::PhantomData, + ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, + RangeToInclusive}, + sync::{ + Arc, + atomic::{AtomicUsize, Ordering} + }, +}; + +#[doc(hidden)] +pub use downcast::{Any, Downcast}; +#[doc(hidden)] +pub use fragile::Fragile; + +/// For mocking static methods +#[doc(hidden)] +pub use lazy_static::lazy_static; + +pub use predicates::{ + boolean::PredicateBooleanExt, + prelude::{ + Predicate, PredicateBoxExt, PredicateFileContentExt, PredicateStrExt, + predicate + } +}; +#[doc(hidden)] +pub use predicates_tree::CaseTreeExt; + +#[cfg(doc)] +extern crate self as mockall; +#[cfg(doc)] +pub mod examples; + +/// Automatically generate mock types for structs and traits. +/// +/// This is by far the easiest way to use Mockall. It works on almost all +/// traits, and almost all structs that have a single `impl` block. In either +/// case, it will generate a mock struct whose name is the name of the mocked +/// struct/trait prepended with "Mock". For each method of the original, the +/// mock struct will have a method named `expect_whatever` that allows you to +/// set expectations. There will also be one `checkpoint` method that calls +/// [`checkpoint`] for every single mocked method. +/// +/// # Examples +/// +/// The simplest use case is mocking a no-frills trait +/// ``` +/// # use mockall_derive::*; +/// #[automock] +/// pub trait Foo { +/// fn foo(&self, key: i16); +/// } +/// +/// let mock = MockFoo::new(); +/// ``` +/// +/// Mocking a structure: +/// ``` +/// # use mockall_derive::*; +/// struct Foo {} +/// #[automock] +/// impl Foo { +/// fn foo(&self) -> u32 { +/// // ... +/// # unimplemented!() +/// } +/// } +/// ``` +/// +/// You can also mock a trait impl on a struct: +/// ``` +/// # use mockall_derive::*; +/// pub trait Foo { +/// fn foo(&self, key: i16); +/// } +/// struct Bar{} +/// #[automock] +/// impl Foo for Bar { +/// fn foo(&self, key: i16){ +/// // ... +/// # unimplemented!() +/// } +/// } +/// +/// let mock = MockBar::new(); +/// ``` +/// +/// Mocking a trait with associated types requires adding a metaitem to the +/// attribute: +/// ``` +/// # use mockall_derive::*; +/// #[automock(type Item=u32;)] +/// trait Foo { +/// type Item; +/// fn foo(&self) -> Self::Item; +/// } +/// ``` +/// +/// Finally, `#[automock]` can also mock foreign functions. This requires +/// another metaitem to specify the mock module name. +/// +/// ``` +/// # use mockall_derive::*; +/// #[automock(mod mock_ffi;)] +/// extern "C" { +/// pub fn foo() -> u32; +/// } +/// ``` +/// +/// [`checkpoint`]: ../mockall/index.html#checkpoints +/// +/// # Limitations +/// +/// `#[automock]` can't handle everything. There are some cases where +/// you will need to use [`mock`] instead: +/// * Mocking a struct that has multiple `impl` blocks, including +/// structs that implement traits. +/// * Mocking a struct or trait defined in another crate. +/// * Mocking a trait with trait bounds. +/// * If the autogenerated "MockFoo" name isn't acceptable, and you want +/// to choose your own name for the mock structure. +pub use mockall_derive::automock; + +/// Manually mock a structure. +/// +/// Sometimes `automock` can't be used. In those cases you can use `mock!`, +/// which basically involves repeating the struct's or trait's definitions. +/// +/// The format is: +/// +/// * Optional visibility specifier +/// * Real structure name and generics fields +/// * 0 or more methods of the structure, written without bodies, enclosed in a +/// {} block +/// * 0 or more impl blocks implementing traits on the structure, also without +/// bodies. +/// +/// # Examples +/// +/// Mock a trait. This is the simplest use case. +/// ``` +/// # use mockall_derive::mock; +/// trait Foo { +/// fn foo(&self, x: u32); +/// } +/// mock!{ +/// pub MyStruct<T: Clone + 'static> { +/// fn bar(&self) -> u8; +/// } +/// impl<T: Clone + 'static> Foo for MyStruct<T> { +/// fn foo(&self, x: u32); +/// } +/// } +/// # fn main() {} +/// ``` +/// Mocking an unsupported `#[derive(X)]` attribute, e.g. `Clone`, is +/// similar. +/// ``` +/// # use mockall_derive::mock; +/// #[derive(Clone)] +/// struct MyStruct; +/// +/// mock!{ +/// pub MyStruct { +/// fn bar(&self); +/// } +/// impl Clone for MyStruct { +/// fn clone(&self) -> Self; +/// } +/// } +/// # fn main() {} +/// ``` +/// +/// When mocking a generic struct's implementation of a generic trait, use the +/// same namespace for their generic parameters. For example, if you wanted to +/// mock `Rc`, do +/// ``` +/// # use mockall_derive::mock; +/// mock!{ +/// pub Rc<T: 'static> {} +/// impl<T: 'static> AsRef<T> for Rc<T> { +/// fn as_ref(&self) -> &T; +/// } +/// } +/// # fn main() {} +/// ``` +/// *not* +/// ```compile_fail +/// # use mockall_derive::mock; +/// mock!{ +/// pub Rc<Q: 'static> {} +/// impl<T: 'static> AsRef<T> for Rc<T> { +/// fn as_ref(&self) -> &T; +/// } +/// } +/// # fn main() {} +/// ``` +/// Associated types can easily be mocked by specifying a concrete type in the +/// `mock!{}` invocation. +/// ``` +/// # use mockall_derive::mock; +/// mock!{ +/// MyIter {} +/// impl Iterator for MyIter { +/// type Item=u32; +/// +/// fn next(&mut self) -> Option<<Self as Iterator>::Item>; +/// } +/// } +/// # fn main() {} +/// ``` +pub use mockall_derive::mock; + +#[doc(hidden)] +pub trait AnyExpectations : Any + Send + Sync {} +downcast!(dyn AnyExpectations); + +#[doc(hidden)] +pub trait ReturnDefault<O> { + fn maybe_return_default() -> Option<O>; + fn return_default() -> Result<O, &'static str>; +} + +#[derive(Default)] +#[doc(hidden)] +pub struct DefaultReturner<O>(PhantomData<O>); + +::cfg_if::cfg_if! { + if #[cfg(feature = "nightly")] { + impl<O> ReturnDefault<O> for DefaultReturner<O> { + default fn maybe_return_default() -> Option<O> { + None + } + + default fn return_default() -> Result<O, &'static str> { + Err("Can only return default values for types that impl std::Default") + } + } + + impl<O: Default> ReturnDefault<O> for DefaultReturner<O> { + fn maybe_return_default() -> Option<O> { + Some(O::default()) + } + + fn return_default() -> Result<O, &'static str> { + Ok(O::default()) + } + } + } else { + impl<O> ReturnDefault<O> for DefaultReturner<O> { + fn maybe_return_default() -> Option<O> { + None + } + + fn return_default() -> Result<O, &'static str> { + Err("Returning default values requires the \"nightly\" feature") + } + } + } +} + +#[doc(hidden)] +pub struct MaybeDebugger<'a, T>(pub &'a T); +::cfg_if::cfg_if! { + if #[cfg(feature = "nightly")] { + impl<'a, T> Debug for MaybeDebugger<'a, T> { + default fn fmt(&self, f: &mut Formatter<'_>) + -> Result<(), fmt::Error> + { + write!(f, "?") + } + } + impl<'a, T: Debug> Debug for MaybeDebugger<'a, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { + self.0.fmt(f) + } + } + } else { + impl<'a, T> Debug for MaybeDebugger<'a, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "?") + } + } + } +} + +// Though it's not entirely correct, we treat usize::max_value() as +// approximately infinity. +#[derive(Debug)] +#[doc(hidden)] +pub struct TimesRange(Range<usize>); + +impl Default for TimesRange { + fn default() -> TimesRange { + // By default, allow any number of calls + TimesRange(0..usize::max_value()) + } +} + +impl From<usize> for TimesRange { + fn from(n: usize) -> TimesRange { + TimesRange(n..(n+1)) + } +} + +impl From<Range<usize>> for TimesRange { + fn from(r: Range<usize>) -> TimesRange { + assert!(r.end > r.start, "Backwards range"); + TimesRange(r) + } +} + +impl From<RangeFrom<usize>> for TimesRange { + fn from(r: RangeFrom<usize>) -> TimesRange { + TimesRange(r.start..usize::max_value()) + } +} + +impl From<RangeFull> for TimesRange { + fn from(_: RangeFull) -> TimesRange { + TimesRange(0..usize::max_value()) + } +} + +impl From<RangeInclusive<usize>> for TimesRange { + fn from(r: RangeInclusive<usize>) -> TimesRange { + assert!(r.end() >= r.start(), "Backwards range"); + TimesRange(*r.start()..*r.end() + 1) + } +} + +impl From<RangeTo<usize>> for TimesRange { + fn from(r: RangeTo<usize>) -> TimesRange { + TimesRange(0..r.end) + } +} + +impl From<RangeToInclusive<usize>> for TimesRange { + fn from(r: RangeToInclusive<usize>) -> TimesRange { + TimesRange(0..r.end + 1) + } +} + +#[derive(PartialEq)] +#[doc(hidden)] +pub enum ExpectedCalls { + Satisfied, + TooMany, + TooFew, +} + +#[derive(Debug, Default)] +#[doc(hidden)] +pub struct Times{ + /// How many times has the expectation already been called? + count: AtomicUsize, + range: TimesRange +} + +#[doc(hidden)] +impl Times { + pub fn call(&self) -> Result<(), String> { + let count = self.count.fetch_add(1, Ordering::Relaxed) + 1; + if count >= self.range.0.end { + if self.range.0.end == 1 { + Err("should not have been called".to_owned()) + } else { + Err(format!( + "called {} times which is more than the expected {}", + count, + self.range.0.end - 1 + )) + } + } else { + Ok(()) + } + } + + pub fn any(&mut self) { + self.range.0 = 0..usize::max_value(); + } + + /// Return how many times this expectation has been called + pub fn count(&self) -> usize { + self.count.load(Ordering::Relaxed) + } + + /// Has this expectation already been called the maximum allowed number of + /// times? + pub fn is_done(&self) -> bool { + self.count.load(Ordering::Relaxed) >= self.range.0.end - 1 + } + + /// Is it required that this expectation be called an exact number of times, + /// or may it be satisfied by a range of call counts? + pub fn is_exact(&self) -> bool { + (self.range.0.end - self.range.0.start) == 1 + } + + /// Has this expectation already been called the expected number of times? + /// If not, was it too many or too few? + pub fn is_satisfied(&self) -> ExpectedCalls { + let satisfied_lower_bound = self.count.load(Ordering::Relaxed) >= self.range.0.start; + let satisfied_upper_bound = self.count.load(Ordering::Relaxed) < self.range.0.end; + if satisfied_lower_bound && satisfied_upper_bound { + ExpectedCalls::Satisfied + } else if satisfied_lower_bound { + ExpectedCalls::TooMany + } else { + ExpectedCalls::TooFew + } + } + + /// The maximum number of times that this expectation must be called + pub fn maximum(&self) -> usize { + self.range.0.end - 1 + } + + /// The minimum number of times that this expectation must be called + pub fn minimum(&self) -> usize { + self.range.0.start + } + + // https://github.com/rust-lang/rust-clippy/issues/3307 + #[allow(clippy::range_plus_one)] + pub fn n(&mut self, n: usize) { + self.range.0 = n..(n+1); + } + + pub fn never(&mut self) { + self.range.0 = 0..1; + } + + pub fn range(&mut self, range: Range<usize>) { + assert!(range.end > range.start, "Backwards range"); + self.range.0 = range; + } + + pub fn times<T: Into<TimesRange>>(&mut self, t: T) { + self.range = t.into(); + } +} + +/// Non-generic keys to `GenericExpectation` internal storage +#[doc(hidden)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub struct Key(any::TypeId); + +#[doc(hidden)] +impl Key { + pub fn new<T: 'static + ?Sized>() -> Self { + Key(any::TypeId::of::<T>()) + } +} + +#[doc(hidden)] +pub struct SeqHandle { + inner: Arc<SeqInner>, + seq: usize +} + +impl SeqHandle { + /// Tell the Sequence that this expectation has been fully satisfied + pub fn satisfy(&self) { + self.inner.satisfy(self.seq); + } + + /// Verify that this handle was called in the correct order + pub fn verify(&self, desc: &str) { + self.inner.verify(self.seq, desc); + } +} + +#[derive(Default)] +struct SeqInner { + satisfaction_level: AtomicUsize, +} + +impl SeqInner { + /// Record the call identified by `seq` as fully satisfied. + fn satisfy(&self, seq: usize) { + let old_sl = self.satisfaction_level.fetch_add(1, Ordering::Relaxed); + assert_eq!(old_sl, seq, "Method sequence violation. Was an already-satisfied method called another time?"); + } + + /// Verify that the call identified by `seq` was called in the correct order + fn verify(&self, seq: usize, desc: &str) { + assert_eq!(seq, self.satisfaction_level.load(Ordering::Relaxed), + "{}: Method sequence violation", desc) + } +} + +/// Used to enforce that mock calls must happen in the sequence specified. +/// +/// Each expectation must expect to be called a fixed number of times. Once +/// satisfied, the next expectation in the sequence will expect to be called. +/// +/// # Examples +/// ``` +/// # use mockall::*; +/// #[automock] +/// trait Foo { +/// fn foo(&self); +/// fn bar(&self) -> u32; +/// } +/// let mut seq = Sequence::new(); +/// +/// let mut mock0 = MockFoo::new(); +/// let mut mock1 = MockFoo::new(); +/// +/// mock0.expect_foo() +/// .times(1) +/// .returning(|| ()) +/// .in_sequence(&mut seq); +/// +/// mock1.expect_bar() +/// .times(1) +/// .returning(|| 42) +/// .in_sequence(&mut seq); +/// +/// mock0.foo(); +/// mock1.bar(); +/// ``` +/// +/// It is an error to add an expectation to a `Sequence` if its call count is +/// unspecified. +/// ```should_panic(expected = "with an exact call count") +/// # use mockall::*; +/// #[automock] +/// trait Foo { +/// fn foo(&self); +/// } +/// let mut seq = Sequence::new(); +/// +/// let mut mock = MockFoo::new(); +/// mock.expect_foo() +/// .returning(|| ()) +/// .in_sequence(&mut seq); // panics! +/// ``` +#[derive(Default)] +pub struct Sequence { + inner: Arc<SeqInner>, + next_seq: usize, +} + +impl Sequence { + /// Create a new empty [`Sequence`] + pub fn new() -> Self { + Self::default() + } + + /// Not for public consumption, but it must be public so the generated code + /// can call it. + #[doc(hidden)] + pub fn next_handle(&mut self) -> SeqHandle { + let handle = SeqHandle{inner: self.inner.clone(), seq: self.next_seq}; + self.next_seq += 1; + handle + } +} |