agy-superpowers 5.1.4 → 5.1.6

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 (185) hide show
  1. package/package.json +1 -1
  2. package/template/agent/rules/debug-confirmation-policy.md +34 -0
  3. package/template/agent/rules/language-matching.md +32 -0
  4. package/template/agent/skills/rust-developer/SKILL.md +281 -0
  5. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +231 -0
  6. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +124 -0
  7. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +131 -0
  8. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +132 -0
  9. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +95 -0
  10. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +141 -0
  11. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +125 -0
  12. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +127 -0
  13. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +120 -0
  14. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +131 -0
  15. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +156 -0
  16. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +122 -0
  17. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +167 -0
  18. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +134 -0
  19. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +143 -0
  20. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +121 -0
  21. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +143 -0
  22. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +187 -0
  23. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +165 -0
  24. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +177 -0
  25. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +163 -0
  26. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +146 -0
  27. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +142 -0
  28. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +160 -0
  29. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +125 -0
  30. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +162 -0
  31. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +177 -0
  32. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +184 -0
  33. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +168 -0
  34. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +182 -0
  35. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +199 -0
  36. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +175 -0
  37. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +185 -0
  38. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +203 -0
  39. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +171 -0
  40. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +158 -0
  41. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +195 -0
  42. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +171 -0
  43. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +156 -0
  44. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +191 -0
  45. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +198 -0
  46. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +154 -0
  47. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +167 -0
  48. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +169 -0
  49. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +172 -0
  50. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +189 -0
  51. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +113 -0
  52. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +147 -0
  53. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +122 -0
  54. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +161 -0
  55. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +149 -0
  56. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +138 -0
  57. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +169 -0
  58. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +116 -0
  59. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +128 -0
  60. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +136 -0
  61. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +131 -0
  62. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +179 -0
  63. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +144 -0
  64. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +152 -0
  65. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +145 -0
  66. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +133 -0
  67. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +152 -0
  68. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +124 -0
  69. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +115 -0
  70. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +151 -0
  71. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +130 -0
  72. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +155 -0
  73. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +171 -0
  74. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +138 -0
  75. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +107 -0
  76. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +154 -0
  77. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +118 -0
  78. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +157 -0
  79. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +133 -0
  80. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +131 -0
  81. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +136 -0
  82. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +135 -0
  83. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +122 -0
  84. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +172 -0
  85. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +168 -0
  86. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +142 -0
  87. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +168 -0
  88. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +147 -0
  89. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +158 -0
  90. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +139 -0
  91. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +147 -0
  92. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +149 -0
  93. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +174 -0
  94. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +159 -0
  95. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +138 -0
  96. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +142 -0
  97. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +156 -0
  98. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +172 -0
  99. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +164 -0
  100. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +99 -0
  101. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +104 -0
  102. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +94 -0
  103. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +78 -0
  104. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +76 -0
  105. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +123 -0
  106. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +127 -0
  107. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +129 -0
  108. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +131 -0
  109. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +142 -0
  110. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +86 -0
  111. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +154 -0
  112. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +118 -0
  113. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +92 -0
  114. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +65 -0
  115. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +101 -0
  116. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +161 -0
  117. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +187 -0
  118. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +142 -0
  119. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +152 -0
  120. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +141 -0
  121. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +181 -0
  122. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +160 -0
  123. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +171 -0
  124. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +130 -0
  125. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +167 -0
  126. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +144 -0
  127. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +154 -0
  128. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +141 -0
  129. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +95 -0
  130. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +135 -0
  131. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +124 -0
  132. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +135 -0
  133. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +134 -0
  134. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +134 -0
  135. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +105 -0
  136. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +65 -0
  137. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +97 -0
  138. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +122 -0
  139. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +119 -0
  140. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +153 -0
  141. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +136 -0
  142. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +133 -0
  143. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +120 -0
  144. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +137 -0
  145. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +134 -0
  146. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +150 -0
  147. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +123 -0
  148. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +113 -0
  149. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +175 -0
  150. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +149 -0
  151. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +142 -0
  152. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +133 -0
  153. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +148 -0
  154. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +130 -0
  155. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +120 -0
  156. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +155 -0
  157. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +139 -0
  158. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +135 -0
  159. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +162 -0
  160. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +186 -0
  161. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +162 -0
  162. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +160 -0
  163. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +151 -0
  164. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +171 -0
  165. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +142 -0
  166. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +168 -0
  167. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +151 -0
  168. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +144 -0
  169. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +189 -0
  170. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +226 -0
  171. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +161 -0
  172. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +130 -0
  173. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +154 -0
  174. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +127 -0
  175. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +154 -0
  176. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +142 -0
  177. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +146 -0
  178. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +160 -0
  179. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +159 -0
  180. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +144 -0
  181. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +137 -0
  182. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +188 -0
  183. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +143 -0
  184. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +131 -0
  185. package/template/agent/skills/systematic-debugging/SKILL.md +17 -0
@@ -0,0 +1,130 @@
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
@@ -0,0 +1,154 @@
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
@@ -0,0 +1,127 @@
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
@@ -0,0 +1,154 @@
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
@@ -0,0 +1,142 @@
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