agy-superpowers 5.2.2 → 5.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/rules/scratch-scripts.md +37 -0
  4. package/template/agent/rules/superpowers.md +4 -51
  5. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  6. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  7. package/template/agent/skills/api-design/SKILL.md +0 -193
  8. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  9. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  10. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  11. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  12. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  13. package/template/agent/skills/community-manager/SKILL.md +0 -115
  14. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  15. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  16. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  17. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  18. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  19. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  20. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  21. package/template/agent/skills/game-design/SKILL.md +0 -194
  22. package/template/agent/skills/game-developer/SKILL.md +0 -175
  23. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  24. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  25. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  26. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  27. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  28. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  29. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  30. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  31. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  32. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  33. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  34. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  35. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  36. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  37. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  38. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  39. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  40. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  41. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  42. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  43. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  44. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  45. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  46. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  47. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  48. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  49. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  50. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  53. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  54. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  55. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  56. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  57. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  58. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  59. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  60. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  61. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  62. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  63. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  64. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  65. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  68. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  69. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  70. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  71. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  72. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  73. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  74. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  75. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  76. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  77. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  78. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  79. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  80. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  83. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  84. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  85. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  86. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  87. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  88. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  89. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  90. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  91. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  92. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  93. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  94. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  95. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  96. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  97. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  98. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  99. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  100. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  101. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  102. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  103. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  104. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  105. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  106. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  107. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  108. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  109. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  110. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  111. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  112. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  113. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  114. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  115. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  116. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  117. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  118. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  119. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  120. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  121. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  122. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  123. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  124. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  125. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  126. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  127. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  128. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  129. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  132. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  133. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  134. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  135. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  136. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  137. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  138. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  139. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  140. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  141. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  142. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  143. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  144. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  148. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  149. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  150. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  151. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  152. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  153. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  154. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  155. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  156. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  157. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  158. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  159. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  160. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  161. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  162. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  163. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  164. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  165. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  166. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  167. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  168. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  169. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  170. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  171. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  172. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  173. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  174. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  175. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  176. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  177. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  178. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  179. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  180. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  181. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  182. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  183. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  184. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  185. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  186. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  187. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  188. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  189. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  190. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  191. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  192. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  193. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  194. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  195. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  196. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  197. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  198. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  199. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  200. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  201. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  202. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  203. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  204. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  205. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  206. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  207. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  208. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  209. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  210. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  211. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  212. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  213. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  214. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  215. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  216. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  217. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  218. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  219. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  220. package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
@@ -1,130 +0,0 @@
1
- # test-should-panic
2
-
3
- > Use `#[should_panic]` to test that code panics as expected
4
-
5
- ## Why It Matters
6
-
7
- Some code should panic on invalid inputs or invariant violations. `#[should_panic]` verifies the panic occurs, optionally checking the panic message. This ensures defensive panics work correctly and documents expected panic conditions.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- #[test]
13
- fn test_panic() {
14
- // Just calling panicking code makes test fail
15
- divide(1, 0); // Test fails with panic
16
- }
17
-
18
- // Using catch_unwind is verbose
19
- #[test]
20
- fn test_panic_manual() {
21
- let result = std::panic::catch_unwind(|| divide(1, 0));
22
- assert!(result.is_err());
23
- }
24
- ```
25
-
26
- ## Good
27
-
28
- ```rust
29
- #[test]
30
- #[should_panic]
31
- fn divide_by_zero_panics() {
32
- divide(1, 0); // Test passes when this panics
33
- }
34
-
35
- // With expected message
36
- #[test]
37
- #[should_panic(expected = "division by zero")]
38
- fn divide_by_zero_panics_with_message() {
39
- divide(1, 0); // Panics with "division by zero"
40
- }
41
-
42
- // Partial message match
43
- #[test]
44
- #[should_panic(expected = "index out of bounds")]
45
- fn index_panic_contains_message() {
46
- let v = vec![1, 2, 3];
47
- let _ = v[100]; // Message contains "index out of bounds"
48
- }
49
- ```
50
-
51
- ## Testing Invariants
52
-
53
- ```rust
54
- struct NonEmpty<T>(Vec<T>);
55
-
56
- impl<T> NonEmpty<T> {
57
- fn new(items: Vec<T>) -> Self {
58
- assert!(!items.is_empty(), "NonEmpty cannot be empty");
59
- NonEmpty(items)
60
- }
61
- }
62
-
63
- #[test]
64
- #[should_panic(expected = "NonEmpty cannot be empty")]
65
- fn non_empty_rejects_empty_vec() {
66
- NonEmpty::new(Vec::<i32>::new());
67
- }
68
-
69
- #[test]
70
- fn non_empty_accepts_non_empty_vec() {
71
- let ne = NonEmpty::new(vec![1, 2, 3]);
72
- assert_eq!(ne.0.len(), 3);
73
- }
74
- ```
75
-
76
- ## With expect() Messages
77
-
78
- ```rust
79
- fn get_config_value(key: &str) -> String {
80
- CONFIG.get(key)
81
- .expect(&format!("missing required config: {}", key))
82
- .to_string()
83
- }
84
-
85
- #[test]
86
- #[should_panic(expected = "missing required config: DATABASE_URL")]
87
- fn missing_config_panics_with_key() {
88
- get_config_value("DATABASE_URL");
89
- }
90
- ```
91
-
92
- ## When NOT to Use should_panic
93
-
94
- ```rust
95
- // ❌ For recoverable errors - use Result
96
- #[test]
97
- #[should_panic] // Wrong: this should return Err, not panic
98
- fn invalid_input_panics() {
99
- parse_config("invalid"); // Should return Err, not panic
100
- }
101
-
102
- // ✅ Return Result and test the error
103
- #[test]
104
- fn invalid_input_returns_error() {
105
- let result = parse_config("invalid");
106
- assert!(result.is_err());
107
- }
108
- ```
109
-
110
- ## Combining with Result
111
-
112
- ```rust
113
- #[test]
114
- #[should_panic]
115
- fn test_panics() -> Result<(), Error> {
116
- // Can combine with Result for setup
117
- let data = setup_test_data()?;
118
-
119
- // This should panic
120
- process_invalid(&data);
121
-
122
- Ok(()) // Never reached
123
- }
124
- ```
125
-
126
- ## See Also
127
-
128
- - [err-result-over-panic](./err-result-over-panic.md) - Panic vs Result
129
- - [err-expect-bugs-only](./err-expect-bugs-only.md) - When to use expect
130
- - [test-descriptive-names](./test-descriptive-names.md) - Test naming
@@ -1,154 +0,0 @@
1
- # test-tokio-async
2
-
3
- > Use `#[tokio::test]` for async tests
4
-
5
- ## Why It Matters
6
-
7
- Async functions can't be called directly—they need a runtime to drive them. `#[tokio::test]` provides a Tokio runtime for your test, handling setup automatically. This is simpler than manually creating a runtime and essential for testing async code.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Won't compile - async fn can't be called without runtime
13
- #[test]
14
- async fn test_async_function() { // Error!
15
- let result = fetch_data().await;
16
- assert!(result.is_ok());
17
- }
18
-
19
- // Manual runtime - verbose and error-prone
20
- #[test]
21
- fn test_async_function() {
22
- let rt = tokio::runtime::Runtime::new().unwrap();
23
- rt.block_on(async {
24
- let result = fetch_data().await;
25
- assert!(result.is_ok());
26
- });
27
- }
28
- ```
29
-
30
- ## Good
31
-
32
- ```rust
33
- #[tokio::test]
34
- async fn test_async_function() {
35
- let result = fetch_data().await;
36
- assert!(result.is_ok());
37
- }
38
-
39
- #[tokio::test]
40
- async fn test_concurrent_operations() {
41
- let (a, b) = tokio::join!(
42
- fetch_user(1),
43
- fetch_user(2),
44
- );
45
- assert!(a.is_ok());
46
- assert!(b.is_ok());
47
- }
48
- ```
49
-
50
- ## Runtime Configuration
51
-
52
- ```rust
53
- // Multi-threaded runtime (default)
54
- #[tokio::test]
55
- async fn test_default_runtime() {
56
- // Uses multi-thread runtime
57
- }
58
-
59
- // Single-threaded (current_thread)
60
- #[tokio::test(flavor = "current_thread")]
61
- async fn test_single_threaded() {
62
- // Simpler, deterministic
63
- }
64
-
65
- // With specific thread count
66
- #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
67
- async fn test_with_workers() {
68
- // Exactly 2 worker threads
69
- }
70
-
71
- // With time control
72
- #[tokio::test(start_paused = true)]
73
- async fn test_with_time_control() {
74
- // Time starts paused for deterministic testing
75
- tokio::time::advance(Duration::from_secs(60)).await;
76
- }
77
- ```
78
-
79
- ## Testing Timeouts
80
-
81
- ```rust
82
- use tokio::time::{timeout, Duration};
83
-
84
- #[tokio::test]
85
- async fn test_operation_completes_in_time() {
86
- let result = timeout(
87
- Duration::from_secs(5),
88
- slow_operation()
89
- ).await;
90
-
91
- assert!(result.is_ok(), "Operation timed out");
92
- }
93
-
94
- #[tokio::test]
95
- async fn test_timeout_triggers() {
96
- let result = timeout(
97
- Duration::from_millis(100),
98
- never_completes()
99
- ).await;
100
-
101
- assert!(result.is_err(), "Expected timeout");
102
- }
103
- ```
104
-
105
- ## Testing Channels
106
-
107
- ```rust
108
- use tokio::sync::mpsc;
109
-
110
- #[tokio::test]
111
- async fn test_channel_communication() {
112
- let (tx, mut rx) = mpsc::channel(10);
113
-
114
- tokio::spawn(async move {
115
- tx.send("hello").await.unwrap();
116
- tx.send("world").await.unwrap();
117
- });
118
-
119
- assert_eq!(rx.recv().await, Some("hello"));
120
- assert_eq!(rx.recv().await, Some("world"));
121
- assert_eq!(rx.recv().await, None);
122
- }
123
- ```
124
-
125
- ## Testing with Mocks
126
-
127
- ```rust
128
- use mockall::*;
129
-
130
- #[automock]
131
- #[async_trait::async_trait]
132
- trait Database {
133
- async fn get_user(&self, id: u64) -> Option<User>;
134
- }
135
-
136
- #[tokio::test]
137
- async fn test_with_mock_database() {
138
- let mut mock = MockDatabase::new();
139
- mock.expect_get_user()
140
- .with(eq(42))
141
- .returning(|_| Some(User { id: 42, name: "Alice".into() }));
142
-
143
- let service = UserService::new(mock);
144
- let user = service.find_user(42).await;
145
-
146
- assert_eq!(user.unwrap().name, "Alice");
147
- }
148
- ```
149
-
150
- ## See Also
151
-
152
- - [async-tokio-runtime](./async-tokio-runtime.md) - Runtime configuration
153
- - [test-mock-traits](./test-mock-traits.md) - Mocking async traits
154
- - [test-fixture-raii](./test-fixture-raii.md) - Async test cleanup
@@ -1,127 +0,0 @@
1
- # test-use-super
2
-
3
- > Use `use super::*;` in test modules to access parent module items
4
-
5
- ## Why It Matters
6
-
7
- The test module is a child of the module being tested. `use super::*` imports all items from the parent module, including private ones. This gives tests access to both public API and internal implementation details for thorough testing.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Verbose imports
13
- #[cfg(test)]
14
- mod tests {
15
- use crate::my_module::public_function;
16
- use crate::my_module::MyStruct;
17
- // Can't access private items this way!
18
-
19
- #[test]
20
- fn test_function() {
21
- let result = public_function();
22
- // ...
23
- }
24
- }
25
- ```
26
-
27
- ## Good
28
-
29
- ```rust
30
- // src/my_module.rs
31
- pub struct PublicStruct { ... }
32
- struct PrivateStruct { ... } // Private
33
-
34
- pub fn public_function() -> i32 { ... }
35
- fn private_helper() -> i32 { ... } // Private
36
-
37
- #[cfg(test)]
38
- mod tests {
39
- use super::*; // Imports everything from parent
40
-
41
- #[test]
42
- fn test_public_struct() {
43
- let s = PublicStruct::new();
44
- // ...
45
- }
46
-
47
- #[test]
48
- fn test_private_struct() {
49
- let s = PrivateStruct::new(); // Can access private!
50
- // ...
51
- }
52
-
53
- #[test]
54
- fn test_private_helper() {
55
- assert_eq!(private_helper(), 42); // Can test private!
56
- }
57
- }
58
- ```
59
-
60
- ## Selective Imports
61
-
62
- ```rust
63
- #[cfg(test)]
64
- mod tests {
65
- // When you want to be explicit
66
- use super::{parse, ParseError, Token};
67
-
68
- // Or import all plus test utilities
69
- use super::*;
70
- use std::fs;
71
- use tempfile::TempDir;
72
-
73
- #[test]
74
- fn test_parse() { ... }
75
- }
76
- ```
77
-
78
- ## Nested Modules
79
-
80
- ```rust
81
- mod outer {
82
- pub fn outer_fn() -> i32 { 1 }
83
-
84
- mod inner {
85
- pub fn inner_fn() -> i32 { 2 }
86
-
87
- #[cfg(test)]
88
- mod tests {
89
- use super::*; // Gets inner's items
90
- use super::super::*; // Gets outer's items
91
-
92
- #[test]
93
- fn test_inner() {
94
- assert_eq!(inner_fn(), 2);
95
- assert_eq!(outer_fn(), 1);
96
- }
97
- }
98
- }
99
- }
100
- ```
101
-
102
- ## With External Dependencies
103
-
104
- ```rust
105
- #[cfg(test)]
106
- mod tests {
107
- use super::*;
108
-
109
- // Test-only dependencies
110
- use proptest::prelude::*;
111
- use mockall::predicate::*;
112
-
113
- proptest! {
114
- #[test]
115
- fn test_property(s: String) {
116
- let result = process(&s);
117
- prop_assert!(result.is_ok());
118
- }
119
- }
120
- }
121
- ```
122
-
123
- ## See Also
124
-
125
- - [test-cfg-test-module](./test-cfg-test-module.md) - Test module structure
126
- - [test-integration-dir](./test-integration-dir.md) - Integration tests
127
- - [proj-pub-crate-internal](./proj-pub-crate-internal.md) - Visibility modifiers
@@ -1,154 +0,0 @@
1
- # type-enum-states
2
-
3
- > Use enums for mutually exclusive states
4
-
5
- ## Why It Matters
6
-
7
- When a value can be in exactly one of several states, an enum makes invalid states unrepresentable. The compiler ensures all states are handled. Contrast with boolean flags or optional fields that can represent impossible combinations.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- struct Connection {
13
- is_connected: bool,
14
- is_authenticated: bool,
15
- is_disconnected: bool, // Can all three be true? False?
16
- socket: Option<TcpStream>,
17
- credentials: Option<Credentials>,
18
- }
19
-
20
- // Possible invalid states:
21
- // - is_connected && is_disconnected (contradiction)
22
- // - is_authenticated && !is_connected (impossible)
23
- // - socket is None but is_connected is true (inconsistent)
24
- ```
25
-
26
- ## Good
27
-
28
- ```rust
29
- enum ConnectionState {
30
- Disconnected,
31
- Connecting { address: SocketAddr },
32
- Connected { socket: TcpStream },
33
- Authenticated { socket: TcpStream, session: Session },
34
- Failed { error: ConnectionError },
35
- }
36
-
37
- struct Connection {
38
- state: ConnectionState,
39
- }
40
-
41
- // Impossible states are unrepresentable
42
- // Each state has exactly the data it needs
43
- ```
44
-
45
- ## Pattern Matching Ensures Completeness
46
-
47
- ```rust
48
- fn handle_connection(conn: &Connection) {
49
- match &conn.state {
50
- ConnectionState::Disconnected => {
51
- println!("Not connected");
52
- }
53
- ConnectionState::Connecting { address } => {
54
- println!("Connecting to {}", address);
55
- }
56
- ConnectionState::Connected { socket } => {
57
- println!("Connected, not authenticated");
58
- }
59
- ConnectionState::Authenticated { socket, session } => {
60
- println!("Authenticated as {}", session.user);
61
- }
62
- ConnectionState::Failed { error } => {
63
- println!("Failed: {}", error);
64
- }
65
- }
66
- // Compiler error if any state is missing
67
- }
68
- ```
69
-
70
- ## State Transitions
71
-
72
- ```rust
73
- impl Connection {
74
- fn connect(&mut self, addr: SocketAddr) -> Result<(), Error> {
75
- match &self.state {
76
- ConnectionState::Disconnected => {
77
- self.state = ConnectionState::Connecting { address: addr };
78
- Ok(())
79
- }
80
- _ => Err(Error::AlreadyConnected),
81
- }
82
- }
83
-
84
- fn on_connected(&mut self, socket: TcpStream) {
85
- if let ConnectionState::Connecting { .. } = &self.state {
86
- self.state = ConnectionState::Connected { socket };
87
- }
88
- }
89
-
90
- fn authenticate(&mut self, creds: Credentials) -> Result<(), Error> {
91
- match std::mem::replace(&mut self.state, ConnectionState::Disconnected) {
92
- ConnectionState::Connected { socket } => {
93
- let session = perform_auth(&socket, creds)?;
94
- self.state = ConnectionState::Authenticated { socket, session };
95
- Ok(())
96
- }
97
- other => {
98
- self.state = other;
99
- Err(Error::NotConnected)
100
- }
101
- }
102
- }
103
- }
104
- ```
105
-
106
- ## Result and Option as State Enums
107
-
108
- ```rust
109
- // Option<T> is an enum for "might not exist"
110
- enum Option<T> {
111
- Some(T),
112
- None,
113
- }
114
-
115
- // Result<T, E> is an enum for "might have failed"
116
- enum Result<T, E> {
117
- Ok(T),
118
- Err(E),
119
- }
120
-
121
- // Use these instead of nullable/sentinel values
122
- fn find_user(id: u64) -> Option<User> { ... }
123
- fn parse_config(s: &str) -> Result<Config, ParseError> { ... }
124
- ```
125
-
126
- ## Avoid Boolean Flags
127
-
128
- ```rust
129
- // Bad: boolean flags
130
- struct Task {
131
- is_running: bool,
132
- is_completed: bool,
133
- is_failed: bool,
134
- error: Option<Error>,
135
- }
136
-
137
- // Good: enum state
138
- enum TaskState {
139
- Pending,
140
- Running { started_at: Instant },
141
- Completed { result: Output },
142
- Failed { error: Error },
143
- }
144
-
145
- struct Task {
146
- state: TaskState,
147
- }
148
- ```
149
-
150
- ## See Also
151
-
152
- - [api-typestate](./api-typestate.md) - Type-level state machines
153
- - [api-non-exhaustive](./api-non-exhaustive.md) - Forward-compatible enums
154
- - [type-option-nullable](./type-option-nullable.md) - Option for optional values
@@ -1,142 +0,0 @@
1
- # type-generic-bounds
2
-
3
- > Add trait bounds only where needed, prefer where clauses for readability
4
-
5
- ## Why It Matters
6
-
7
- Trait bounds constrain what types can be used with generic code. Adding unnecessary bounds limits flexibility. Adding bounds in the right place (impl vs function vs where clause) affects usability and readability. Well-placed bounds keep APIs flexible while ensuring type safety.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Bounds on struct definition - limits all uses
13
- struct Container<T: Clone + Debug> { // Even storage requires Clone?
14
- items: Vec<T>,
15
- }
16
-
17
- // Inline bounds make signature hard to read
18
- fn process<T: Clone + Debug + Send + Sync + 'static, E: Error + Send + Clone>(
19
- value: T
20
- ) -> Result<T, E> { ... }
21
-
22
- // Redundant bounds
23
- fn print_twice<T: Clone + Debug>(value: T)
24
- where
25
- T: Clone, // Already specified above
26
- { ... }
27
- ```
28
-
29
- ## Good
30
-
31
- ```rust
32
- // No bounds on struct - store anything
33
- struct Container<T> {
34
- items: Vec<T>,
35
- }
36
-
37
- // Bounds only on impls that need them
38
- impl<T: Clone> Container<T> {
39
- fn duplicate(&self) -> Self {
40
- Container { items: self.items.clone() }
41
- }
42
- }
43
-
44
- impl<T: Debug> Container<T> {
45
- fn debug_print(&self) {
46
- println!("{:?}", self.items);
47
- }
48
- }
49
-
50
- // Where clause for readability
51
- fn process<T, E>(value: T) -> Result<T, E>
52
- where
53
- T: Clone + Debug + Send + Sync + 'static,
54
- E: Error + Send + Clone,
55
- { ... }
56
- ```
57
-
58
- ## Bound Placement
59
-
60
- ```rust
61
- // On struct: affects all uses of the type
62
- struct MustBeClone<T: Clone> { data: T } // Rarely needed
63
-
64
- // On impl: affects specific functionality
65
- impl<T: Clone> Container<T> { ... } // Common pattern
66
-
67
- // On function: affects that function only
68
- fn requires_send<T: Send>(value: T) { ... }
69
-
70
- // Recommendation: start with no bounds, add as needed
71
- ```
72
-
73
- ## Where Clause Benefits
74
-
75
- ```rust
76
- // Inline: hard to read
77
- fn complex<T: Clone + Debug + Send, U: AsRef<str> + Into<String>>(t: T, u: U) { }
78
-
79
- // Where clause: clear and scannable
80
- fn complex<T, U>(t: T, u: U)
81
- where
82
- T: Clone + Debug + Send,
83
- U: AsRef<str> + Into<String>,
84
- { }
85
-
86
- // Essential for complex bounds
87
- fn foo<T, U>(t: T, u: U)
88
- where
89
- T: Iterator<Item = U>,
90
- U: Clone + Into<String>,
91
- Vec<U>: Debug, // Bounds on expressions
92
- { }
93
- ```
94
-
95
- ## Implied Bounds
96
-
97
- ```rust
98
- // Supertrait bounds are implied
99
- trait Foo: Clone + Debug {}
100
-
101
- fn process<T: Foo>(value: T) {
102
- // T: Clone and T: Debug are implied by T: Foo
103
- let cloned = value.clone();
104
- println!("{:?}", cloned);
105
- }
106
-
107
- // Associated type bounds
108
- fn process<I>(iter: I)
109
- where
110
- I: Iterator,
111
- I::Item: Clone, // Bound on associated type
112
- { }
113
- ```
114
-
115
- ## Conditional Trait Implementation
116
-
117
- ```rust
118
- struct Wrapper<T>(T);
119
-
120
- // Implement Clone only when T: Clone
121
- impl<T: Clone> Clone for Wrapper<T> {
122
- fn clone(&self) -> Self {
123
- Wrapper(self.0.clone())
124
- }
125
- }
126
-
127
- // Implement Debug only when T: Debug
128
- impl<T: Debug> Debug for Wrapper<T> {
129
- fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
130
- f.debug_tuple("Wrapper").field(&self.0).finish()
131
- }
132
- }
133
-
134
- // Wrapper<i32> is Clone + Debug
135
- // Wrapper<NonCloneable> is neither
136
- ```
137
-
138
- ## See Also
139
-
140
- - [api-impl-into](./api-impl-into.md) - Using Into bounds
141
- - [api-impl-asref](./api-impl-asref.md) - Using AsRef bounds
142
- - [name-type-param-single](./name-type-param-single.md) - Type parameter naming