red64-cli 0.5.0 → 0.6.0

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 (62) hide show
  1. package/README.md +64 -58
  2. package/dist/components/screens/StartScreen.d.ts.map +1 -1
  3. package/dist/components/screens/StartScreen.js +2 -2
  4. package/dist/components/screens/StartScreen.js.map +1 -1
  5. package/dist/services/AgentInvoker.js +4 -4
  6. package/dist/services/AgentInvoker.js.map +1 -1
  7. package/dist/services/ClaudeHealthCheck.d.ts +5 -0
  8. package/dist/services/ClaudeHealthCheck.d.ts.map +1 -1
  9. package/dist/services/ClaudeHealthCheck.js +43 -5
  10. package/dist/services/ClaudeHealthCheck.js.map +1 -1
  11. package/dist/services/index.d.ts +1 -1
  12. package/dist/services/index.d.ts.map +1 -1
  13. package/dist/services/index.js +1 -1
  14. package/dist/services/index.js.map +1 -1
  15. package/framework/stacks/c/code-quality.md +326 -0
  16. package/framework/stacks/c/coding-style.md +347 -0
  17. package/framework/stacks/c/conventions.md +513 -0
  18. package/framework/stacks/c/error-handling.md +350 -0
  19. package/framework/stacks/c/feedback.md +158 -0
  20. package/framework/stacks/c/memory-safety.md +408 -0
  21. package/framework/stacks/c/tech.md +122 -0
  22. package/framework/stacks/c/testing.md +472 -0
  23. package/framework/stacks/cpp/code-quality.md +282 -0
  24. package/framework/stacks/cpp/coding-style.md +363 -0
  25. package/framework/stacks/cpp/conventions.md +420 -0
  26. package/framework/stacks/cpp/error-handling.md +264 -0
  27. package/framework/stacks/cpp/feedback.md +104 -0
  28. package/framework/stacks/cpp/memory-safety.md +351 -0
  29. package/framework/stacks/cpp/tech.md +160 -0
  30. package/framework/stacks/cpp/testing.md +323 -0
  31. package/framework/stacks/java/code-quality.md +357 -0
  32. package/framework/stacks/java/coding-style.md +400 -0
  33. package/framework/stacks/java/conventions.md +437 -0
  34. package/framework/stacks/java/error-handling.md +408 -0
  35. package/framework/stacks/java/feedback.md +180 -0
  36. package/framework/stacks/java/tech.md +126 -0
  37. package/framework/stacks/java/testing.md +485 -0
  38. package/framework/stacks/javascript/async-patterns.md +216 -0
  39. package/framework/stacks/javascript/code-quality.md +182 -0
  40. package/framework/stacks/javascript/coding-style.md +293 -0
  41. package/framework/stacks/javascript/conventions.md +268 -0
  42. package/framework/stacks/javascript/error-handling.md +216 -0
  43. package/framework/stacks/javascript/feedback.md +80 -0
  44. package/framework/stacks/javascript/tech.md +114 -0
  45. package/framework/stacks/javascript/testing.md +209 -0
  46. package/framework/stacks/loco/code-quality.md +156 -0
  47. package/framework/stacks/loco/coding-style.md +247 -0
  48. package/framework/stacks/loco/error-handling.md +225 -0
  49. package/framework/stacks/loco/feedback.md +35 -0
  50. package/framework/stacks/loco/loco.md +342 -0
  51. package/framework/stacks/loco/structure.md +193 -0
  52. package/framework/stacks/loco/tech.md +129 -0
  53. package/framework/stacks/loco/testing.md +211 -0
  54. package/framework/stacks/rust/code-quality.md +370 -0
  55. package/framework/stacks/rust/coding-style.md +475 -0
  56. package/framework/stacks/rust/conventions.md +430 -0
  57. package/framework/stacks/rust/error-handling.md +399 -0
  58. package/framework/stacks/rust/feedback.md +152 -0
  59. package/framework/stacks/rust/memory-safety.md +398 -0
  60. package/framework/stacks/rust/tech.md +121 -0
  61. package/framework/stacks/rust/testing.md +528 -0
  62. package/package.json +14 -2
@@ -0,0 +1,472 @@
1
+ # Testing Patterns
2
+
3
+ Comprehensive testing patterns for C projects with Unity (primary) and CMocka (alternative) test frameworks.
4
+
5
+ ---
6
+
7
+ ## Philosophy
8
+
9
+ - **Fast feedback**: Unit tests run in milliseconds, no I/O
10
+ - **Arrange-Act-Assert**: Every test follows the same three-step structure
11
+ - **Test behavior, not implementation**: Tests should survive refactoring
12
+ - **Sanitizers always on**: Run tests under ASan + UBSan in CI
13
+
14
+ ---
15
+
16
+ ## Test Organization
17
+
18
+ ```
19
+ tests/
20
+ CMakeLists.txt
21
+ unit/
22
+ test_user.c
23
+ test_config.c
24
+ test_parser.c
25
+ integration/
26
+ test_database.c
27
+ test_http_client.c
28
+ fuzz/
29
+ fuzz_parser.c
30
+ fixtures/
31
+ sample_config.json
32
+ test_data.bin
33
+ ```
34
+
35
+ **Pattern**: Mirror `src/` structure. Prefix all test files with `test_`. Register all tests in CTest.
36
+
37
+ ---
38
+
39
+ ## Unity Test Framework (Primary)
40
+
41
+ ### Basic Test Structure
42
+
43
+ ```c
44
+ #include "unity.h"
45
+ #include "myproject/math_utils.h"
46
+
47
+ void setUp(void) {
48
+ /* Called before each test -- allocate shared resources */
49
+ }
50
+
51
+ void tearDown(void) {
52
+ /* Called after each test -- free shared resources */
53
+ }
54
+
55
+ void test_add_positive_numbers(void) {
56
+ /* Arrange & Act */
57
+ int result = add(2, 3);
58
+
59
+ /* Assert */
60
+ TEST_ASSERT_EQUAL_INT(5, result);
61
+ }
62
+
63
+ void test_add_negative_numbers(void) {
64
+ TEST_ASSERT_EQUAL_INT(-3, add(-1, -2));
65
+ }
66
+
67
+ void test_add_overflow_returns_error(void) {
68
+ int result;
69
+ int rc = safe_add(INT_MAX, 1, &result);
70
+
71
+ TEST_ASSERT_EQUAL_INT(ERR_OVERFLOW, rc);
72
+ }
73
+
74
+ int main(void) {
75
+ UNITY_BEGIN();
76
+ RUN_TEST(test_add_positive_numbers);
77
+ RUN_TEST(test_add_negative_numbers);
78
+ RUN_TEST(test_add_overflow_returns_error);
79
+ return UNITY_END();
80
+ }
81
+ ```
82
+
83
+ ### Common TEST_ASSERT Macros
84
+
85
+ | Macro | Purpose |
86
+ |---|---|
87
+ | `TEST_ASSERT_EQUAL_INT(expected, actual)` | Compare integers |
88
+ | `TEST_ASSERT_EQUAL_STRING(expected, actual)` | Compare null-terminated strings |
89
+ | `TEST_ASSERT_EQUAL_FLOAT(expected, actual, delta)` | Compare floats within tolerance |
90
+ | `TEST_ASSERT_EQUAL_PTR(expected, actual)` | Compare pointers |
91
+ | `TEST_ASSERT_EQUAL_MEMORY(expected, actual, len)` | Compare raw memory |
92
+ | `TEST_ASSERT_NULL(ptr)` | Assert pointer is NULL |
93
+ | `TEST_ASSERT_NOT_NULL(ptr)` | Assert pointer is not NULL |
94
+ | `TEST_ASSERT_TRUE(condition)` | Assert boolean true |
95
+ | `TEST_ASSERT_FALSE(condition)` | Assert boolean false |
96
+ | `TEST_ASSERT_EQUAL_INT_ARRAY(exp, act, len)` | Compare integer arrays |
97
+
98
+ ### setUp / tearDown with Resources
99
+
100
+ ```c
101
+ static db_t *test_db = NULL;
102
+ static user_repo_t *test_repo = NULL;
103
+
104
+ void setUp(void) {
105
+ test_db = db_open(":memory:");
106
+ TEST_ASSERT_NOT_NULL(test_db);
107
+ db_migrate(test_db);
108
+ test_repo = user_repo_create(test_db);
109
+ TEST_ASSERT_NOT_NULL(test_repo);
110
+ }
111
+
112
+ void tearDown(void) {
113
+ user_repo_destroy(test_repo);
114
+ test_repo = NULL;
115
+ db_close(test_db);
116
+ test_db = NULL;
117
+ }
118
+
119
+ void test_create_user_success(void) {
120
+ /* Arrange */
121
+ create_request_t req = {.name = "Alice", .email = "alice@example.com"};
122
+ user_t user = {0};
123
+
124
+ /* Act */
125
+ int rc = user_repo_create_user(test_repo, &req, &user);
126
+
127
+ /* Assert */
128
+ TEST_ASSERT_EQUAL_INT(ERR_OK, rc);
129
+ TEST_ASSERT_EQUAL_STRING("Alice", user.name);
130
+ TEST_ASSERT_TRUE(user.id > 0);
131
+ }
132
+
133
+ void test_create_user_duplicate_email(void) {
134
+ create_request_t req = {.name = "Alice", .email = "alice@example.com"};
135
+ user_t user = {0};
136
+
137
+ user_repo_create_user(test_repo, &req, &user); /* First create */
138
+ int rc = user_repo_create_user(test_repo, &req, &user); /* Duplicate */
139
+
140
+ TEST_ASSERT_EQUAL_INT(ERR_ALREADY_EXISTS, rc);
141
+ }
142
+ ```
143
+
144
+ ---
145
+
146
+ ## CMocka Alternative
147
+
148
+ ### Basic CMocka Test
149
+
150
+ ```c
151
+ #include <stdarg.h>
152
+ #include <stddef.h>
153
+ #include <setjmp.h>
154
+ #include <cmocka.h>
155
+
156
+ #include "myproject/config.h"
157
+
158
+ static void test_config_load_valid(void **state) {
159
+ (void)state;
160
+
161
+ config_t cfg = {0};
162
+ int rc = config_load("fixtures/valid.json", &cfg);
163
+
164
+ assert_int_equal(ERR_OK, rc);
165
+ assert_string_equal("localhost", cfg.host);
166
+ assert_int_equal(8080, cfg.port);
167
+
168
+ config_free(&cfg);
169
+ }
170
+
171
+ static void test_config_load_missing_file(void **state) {
172
+ (void)state;
173
+
174
+ config_t cfg = {0};
175
+ int rc = config_load("nonexistent.json", &cfg);
176
+
177
+ assert_int_equal(ERR_IO, rc);
178
+ }
179
+
180
+ int main(void) {
181
+ const struct CMUnitTest tests[] = {
182
+ cmocka_unit_test(test_config_load_valid),
183
+ cmocka_unit_test(test_config_load_missing_file),
184
+ };
185
+ return cmocka_run_group_tests(tests, NULL, NULL);
186
+ }
187
+ ```
188
+
189
+ ### CMocka with Setup/Teardown
190
+
191
+ ```c
192
+ static int setup_db(void **state) {
193
+ db_t *db = db_open(":memory:");
194
+ if (!db) return -1;
195
+ db_migrate(db);
196
+ *state = db;
197
+ return 0;
198
+ }
199
+
200
+ static int teardown_db(void **state) {
201
+ db_close((db_t *)*state);
202
+ return 0;
203
+ }
204
+
205
+ static void test_insert_record(void **state) {
206
+ db_t *db = (db_t *)*state;
207
+ int rc = db_insert(db, "test_key", "test_value");
208
+ assert_int_equal(ERR_OK, rc);
209
+ }
210
+
211
+ int main(void) {
212
+ const struct CMUnitTest tests[] = {
213
+ cmocka_unit_test_setup_teardown(test_insert_record, setup_db, teardown_db),
214
+ };
215
+ return cmocka_run_group_tests(tests, NULL, NULL);
216
+ }
217
+ ```
218
+
219
+ ---
220
+
221
+ ## Mocking with Function Pointers
222
+
223
+ In C, dependency injection is achieved via function pointers or vtable-like structs.
224
+
225
+ ```c
226
+ /* GOOD: Define an interface via function pointer struct */
227
+ typedef struct {
228
+ int (*find_by_email)(void *ctx, const char *email, user_t *out);
229
+ int (*save)(void *ctx, const user_t *user);
230
+ void *ctx;
231
+ } user_repo_iface_t;
232
+
233
+ /* Production implementation */
234
+ static int pg_find_by_email(void *ctx, const char *email, user_t *out) {
235
+ pg_conn_t *conn = (pg_conn_t *)ctx;
236
+ /* ... real database query ... */
237
+ return ERR_OK;
238
+ }
239
+
240
+ /* Test mock implementation */
241
+ static user_t mock_user;
242
+ static int mock_save_called = 0;
243
+
244
+ static int mock_find_by_email(void *ctx, const char *email, user_t *out) {
245
+ (void)ctx;
246
+ if (strcmp(email, "alice@example.com") == 0) {
247
+ *out = mock_user;
248
+ return ERR_OK;
249
+ }
250
+ return ERR_NOT_FOUND;
251
+ }
252
+
253
+ static int mock_save(void *ctx, const user_t *user) {
254
+ (void)ctx;
255
+ mock_save_called = 1;
256
+ mock_user = *user;
257
+ return ERR_OK;
258
+ }
259
+
260
+ /* In test */
261
+ void test_create_user_calls_save(void) {
262
+ mock_save_called = 0;
263
+ user_repo_iface_t repo = {
264
+ .find_by_email = mock_find_by_email,
265
+ .save = mock_save,
266
+ .ctx = NULL,
267
+ };
268
+
269
+ create_request_t req = {.name = "Bob", .email = "bob@example.com"};
270
+ user_t result = {0};
271
+ int rc = user_service_create(&repo, &req, &result);
272
+
273
+ TEST_ASSERT_EQUAL_INT(ERR_OK, rc);
274
+ TEST_ASSERT_TRUE(mock_save_called);
275
+ TEST_ASSERT_EQUAL_STRING("Bob", mock_user.name);
276
+ }
277
+ ```
278
+
279
+ ### CMock (Auto-Generated Mocks for Unity)
280
+
281
+ ```bash
282
+ # CMock parses headers and generates mock .c/.h files
283
+ ruby vendor/cmock/lib/cmock.rb include/myproject/user_repo.h
284
+
285
+ # Generates:
286
+ # mocks/mock_user_repo.h
287
+ # mocks/mock_user_repo.c
288
+ ```
289
+
290
+ ```c
291
+ /* Using CMock-generated mocks */
292
+ #include "mock_user_repo.h"
293
+
294
+ void test_service_returns_not_found(void) {
295
+ /* Expect find_by_email to be called and return NOT_FOUND */
296
+ user_repo_find_by_email_ExpectAndReturn("unknown@example.com", NULL, ERR_NOT_FOUND);
297
+
298
+ int rc = user_service_find("unknown@example.com", NULL);
299
+ TEST_ASSERT_EQUAL_INT(ERR_NOT_FOUND, rc);
300
+ }
301
+ ```
302
+
303
+ ---
304
+
305
+ ## Integration Testing
306
+
307
+ ```c
308
+ /* Integration tests use real dependencies (database, filesystem) */
309
+ static char test_dir[256];
310
+
311
+ void setUp(void) {
312
+ snprintf(test_dir, sizeof(test_dir), "/tmp/test_%d", getpid());
313
+ mkdir(test_dir, 0755);
314
+ }
315
+
316
+ void tearDown(void) {
317
+ /* Clean up test directory */
318
+ char cmd[512];
319
+ snprintf(cmd, sizeof(cmd), "rm -rf %s", test_dir);
320
+ system(cmd);
321
+ }
322
+
323
+ void test_config_save_and_load_roundtrip(void) {
324
+ char path[512];
325
+ snprintf(path, sizeof(path), "%s/config.json", test_dir);
326
+
327
+ config_t original = {.host = "localhost", .port = 8080, .debug = true};
328
+ int rc = config_save(&original, path);
329
+ TEST_ASSERT_EQUAL_INT(ERR_OK, rc);
330
+
331
+ config_t loaded = {0};
332
+ rc = config_load(path, &loaded);
333
+ TEST_ASSERT_EQUAL_INT(ERR_OK, rc);
334
+ TEST_ASSERT_EQUAL_STRING("localhost", loaded.host);
335
+ TEST_ASSERT_EQUAL_INT(8080, loaded.port);
336
+ TEST_ASSERT_TRUE(loaded.debug);
337
+
338
+ config_free(&loaded);
339
+ }
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Fuzz Testing with libFuzzer
345
+
346
+ ```c
347
+ /* fuzz/fuzz_parser.c */
348
+ #include "myproject/parser.h"
349
+ #include <stdint.h>
350
+ #include <stddef.h>
351
+
352
+ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
353
+ /* Null-terminate input for string-based parsers */
354
+ char *input = malloc(size + 1);
355
+ if (!input) return 0;
356
+ memcpy(input, data, size);
357
+ input[size] = '\0';
358
+
359
+ result_t result = {0};
360
+ parse(input, &result);
361
+ result_free(&result);
362
+ free(input);
363
+ return 0;
364
+ }
365
+ ```
366
+
367
+ ```cmake
368
+ add_executable(fuzz_parser fuzz/fuzz_parser.c)
369
+ target_compile_options(fuzz_parser PRIVATE -fsanitize=fuzzer,address,undefined)
370
+ target_link_options(fuzz_parser PRIVATE -fsanitize=fuzzer,address,undefined)
371
+ target_link_libraries(fuzz_parser PRIVATE myapp_lib)
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Coverage with gcov / lcov
377
+
378
+ ```bash
379
+ # Build with coverage
380
+ cmake -B build-cov -DCMAKE_BUILD_TYPE=Debug \
381
+ -DCMAKE_C_FLAGS="--coverage"
382
+ cmake --build build-cov
383
+
384
+ # Run tests
385
+ ctest --test-dir build-cov --output-on-failure
386
+
387
+ # Generate HTML report
388
+ lcov --capture --directory build-cov --output-file coverage.info
389
+ lcov --remove coverage.info '/usr/*' '*/test/*' '*/vendor/*' --output-file coverage.info
390
+ genhtml coverage.info --output-directory coverage-report/
391
+
392
+ # Console summary
393
+ gcovr --root . --print-summary
394
+ ```
395
+
396
+ ---
397
+
398
+ ## CTest Integration
399
+
400
+ ```cmake
401
+ # tests/CMakeLists.txt
402
+ enable_testing()
403
+
404
+ # Unity-based tests
405
+ add_executable(test_user tests/unit/test_user.c)
406
+ target_link_libraries(test_user PRIVATE unity myapp_lib)
407
+ add_test(NAME unit_user COMMAND test_user)
408
+ set_tests_properties(unit_user PROPERTIES LABELS "unit")
409
+
410
+ add_executable(test_config tests/unit/test_config.c)
411
+ target_link_libraries(test_config PRIVATE unity myapp_lib)
412
+ add_test(NAME unit_config COMMAND test_config)
413
+ set_tests_properties(unit_config PROPERTIES LABELS "unit")
414
+
415
+ # Integration tests
416
+ add_executable(test_database tests/integration/test_database.c)
417
+ target_link_libraries(test_database PRIVATE unity myapp_lib)
418
+ add_test(NAME integration_database COMMAND test_database)
419
+ set_tests_properties(integration_database PROPERTIES LABELS "integration")
420
+ ```
421
+
422
+ ```bash
423
+ # Run by label
424
+ ctest --test-dir build -L unit --output-on-failure
425
+ ctest --test-dir build -L integration --output-on-failure
426
+
427
+ # Run specific test
428
+ ctest --test-dir build -R "unit_user" -V
429
+
430
+ # Run all tests
431
+ ctest --test-dir build --output-on-failure
432
+ ```
433
+
434
+ ---
435
+
436
+ ## Test Commands Summary
437
+
438
+ ```bash
439
+ # Fast feedback
440
+ ctest --test-dir build -L unit --output-on-failure # Unit tests only
441
+ ctest --test-dir build -R "unit_user" -V # Single suite, verbose
442
+
443
+ # Full suite
444
+ ctest --test-dir build --output-on-failure
445
+
446
+ # With sanitizers
447
+ cmake --build build-asan && ctest --test-dir build-asan --output-on-failure
448
+
449
+ # Fuzz testing
450
+ ./build/fuzz_parser corpus/ -max_total_time=60
451
+
452
+ # Coverage
453
+ cmake --build build-cov && ctest --test-dir build-cov && gcovr --root . --print-summary
454
+ ```
455
+
456
+ ---
457
+
458
+ ## Anti-Patterns
459
+
460
+ | Anti-Pattern | Problem | Correct Approach |
461
+ |---|---|---|
462
+ | Tests that depend on execution order | Flaky, fragile | Independent setUp/tearDown per test |
463
+ | Testing private/static functions directly | Couples tests to implementation | Test through public API |
464
+ | No tearDown cleanup | Memory leaks obscure real bugs | Free all resources in tearDown |
465
+ | Mocking everything | Tests pass but code is broken | Mock boundaries only (I/O, network, DB) |
466
+ | No sanitizers during test | Memory bugs hide | ASan + UBSan on every CI test run |
467
+ | Giant test functions | Hard to diagnose failures | One assertion per logical behavior |
468
+ | No integration tests | Unit tests pass, system fails | Test real dependencies in integration suite |
469
+
470
+ ---
471
+
472
+ _Tests document behavior. Each test should read as a specification of what the code does. Name tests after the scenario, not the function._