Claude Code Plugins

Community-maintained marketplace

Feedback

Mocking skill for the ikigai project

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name mocking
description Mocking skill for the ikigai project

Mocking

Description

MOCKABLE wrapper patterns for testing external dependencies.

Philosophy

Mock external dependencies, never our own code. External means: libraries (talloc, yyjson, curl), system calls (open, read, write, stat), and vendor inline functions.

The MOCKABLE Pattern

wrapper.h provides zero-overhead mocking via weak symbols:

// wrapper.h
#ifdef NDEBUG
    #define MOCKABLE static inline  // Release: zero overhead
#else
    #define MOCKABLE __attribute__((weak))  // Debug: overridable
#endif

MOCKABLE int posix_write_(int fd, const void *buf, size_t count);

Using Mocks in Tests

Override the weak symbol in your test file:

// test_file.c
#include "wrapper.h"

// Override - this replaces the weak symbol
int posix_write_(int fd, const void *buf, size_t count) {
    return -1;  // Simulate write failure
}

void test_write_error_handling(void) {
    // Now any code calling posix_write_() gets our mock
    res_t r = save_file("test.txt", "content");
    assert(IS_ERR(r));
}

Available Wrappers

POSIX System Calls

Wrapper Wraps
posix_open_() open()
posix_close_() close()
posix_read_() read()
posix_write_() write()
posix_stat_() stat()
posix_mkdir_() mkdir()
posix_access_() access()
posix_rename_() rename()
posix_getcwd_() getcwd()
posix_pipe_() pipe()
posix_fcntl_() fcntl()
posix_select_() select()
posix_sigaction_() sigaction()
posix_ioctl_() ioctl()
posix_tcgetattr_() tcgetattr()
posix_tcsetattr_() tcsetattr()
posix_tcflush_() tcflush()

POSIX stdio

Wrapper Wraps
fopen_() fopen()
fclose_() fclose()
fread_() fread()
fwrite_() fwrite()
fseek_() fseek()
ftell_() ftell()
posix_fdopen_() fdopen()
popen_() popen()
pclose_() pclose()
opendir_() opendir()

C Standard Library

Wrapper Wraps
snprintf_() snprintf()
vsnprintf_() vsnprintf()
gmtime_() gmtime()
strftime_() strftime()

talloc

Wrapper Wraps
talloc_zero_() talloc_zero_size()
talloc_strdup_() talloc_strdup()
talloc_array_() talloc_zero_size()
talloc_realloc_() talloc_realloc_size()
talloc_asprintf_() talloc_vasprintf()

yyjson

Wrapper Wraps
yyjson_read_file_() yyjson_read_file()
yyjson_mut_write_file_() yyjson_mut_write_file()
yyjson_read_() yyjson_read()
yyjson_doc_get_root_() yyjson_doc_get_root()
yyjson_obj_get_() yyjson_obj_get()
yyjson_get_sint_() yyjson_get_sint()
yyjson_get_str_() yyjson_get_str()
yyjson_mut_obj_add_str_() yyjson_mut_obj_add_str()
yyjson_mut_obj_add_int_() yyjson_mut_obj_add_int()
yyjson_mut_obj_add_uint_() yyjson_mut_obj_add_uint()
yyjson_mut_obj_() yyjson_mut_obj()
yyjson_mut_arr_() yyjson_mut_arr()
yyjson_mut_obj_add_val_() yyjson_mut_obj_add_val()
yyjson_mut_arr_add_val_() yyjson_mut_arr_add_val()
yyjson_mut_obj_add_bool_() yyjson_mut_obj_add_bool()
yyjson_val_mut_copy_() yyjson_val_mut_copy()

libcurl (Easy API)

Wrapper Wraps
curl_easy_init_() curl_easy_init()
curl_easy_cleanup_() curl_easy_cleanup()
curl_easy_perform_() curl_easy_perform()
curl_easy_setopt_() curl_easy_setopt()
curl_easy_getinfo_() curl_easy_getinfo()
curl_easy_strerror_() curl_easy_strerror()
curl_slist_append_() curl_slist_append()
curl_slist_free_all_() curl_slist_free_all()

libcurl (Multi API)

Wrapper Wraps
curl_multi_init_() curl_multi_init()
curl_multi_cleanup_() curl_multi_cleanup()
curl_multi_add_handle_() curl_multi_add_handle()
curl_multi_remove_handle_() curl_multi_remove_handle()
curl_multi_perform_() curl_multi_perform()
curl_multi_fdset_() curl_multi_fdset()
curl_multi_timeout_() curl_multi_timeout()
curl_multi_info_read_() curl_multi_info_read()
curl_multi_strerror_() curl_multi_strerror()

libpq (PostgreSQL)

Wrapper Wraps
PQgetvalue_() PQgetvalue()
pq_exec_() PQexec()
pq_exec_params_() PQexecParams()
PQresultStatus_() PQresultStatus()

pthread

Wrapper Wraps
pthread_mutex_init_() pthread_mutex_init()
pthread_mutex_destroy_() pthread_mutex_destroy()
pthread_mutex_lock_() pthread_mutex_lock()
pthread_mutex_unlock_() pthread_mutex_unlock()
pthread_create_() pthread_create()
pthread_join_() pthread_join()

Internal ikigai Functions

Wrapper Wraps
ik_db_init_() ik_db_init()
ik_db_message_insert_() ik_db_message_insert()
ik_scrollback_append_line_() ik_scrollback_append_line()
ik_repl_render_frame_() ik_repl_render_frame()
ik_agent_get_provider_() ik_agent_get_provider()
ik_request_build_from_conversation_() ik_request_build_from_conversation()
ik_http_multi_create_() ik_http_multi_create()
ik_http_multi_info_read_() ik_http_multi_info_read()
ik_agent_start_tool_execution_() ik_agent_start_tool_execution()
ik_agent_should_continue_tool_loop_() ik_agent_should_continue_tool_loop()
ik_repl_submit_tool_loop_continuation_() ik_repl_submit_tool_loop_continuation()
ik_agent_add_message_() ik_agent_add_message()
ik_agent_transition_to_idle_() ik_agent_transition_to_idle()

Adding New Wrappers

When you need to mock a new external dependency:

  1. Add declaration to wrapper.h:
MOCKABLE return_type function_name_(args);
  1. Add implementation to wrapper.c:
return_type function_name_(args) {
    return original_function(args);
}
  1. Replace direct calls in production code with the wrapper

  2. Override in tests to inject failures

Wrapping Vendor Inline Functions

Problem: Inline functions like yyjson_doc_get_root() expand at every call site, creating untestable branches.

Solution: Wrap once, use wrapper everywhere:

// sse_parser.h
yyjson_val *yyjson_doc_get_root_wrapper(yyjson_doc *doc);

// sse_parser.c
yyjson_val *yyjson_doc_get_root_wrapper(yyjson_doc *doc) {
    return yyjson_doc_get_root(doc);  // Inline expands here only
}

// Test both branches once
void test_wrapper_null(void) {
    assert(yyjson_doc_get_root_wrapper(NULL) == NULL);
}
void test_wrapper_valid(void) {
    yyjson_doc *doc = create_test_doc();
    assert(yyjson_doc_get_root_wrapper(doc) != NULL);
}

What NOT to Mock

  • Our own code (refactor instead)
  • Pure functions (test directly)
  • Simple data structures

References

  • src/wrapper.h - MOCKABLE declarations
  • src/wrapper.c - Wrapper implementations
  • src/openai/sse_parser.h - Inline wrapper example