11 KiB
JSON-GLib Integration Plan for Issue #15
Overview
This document outlines the complete plan for integrating json-glib into the CProof (profanity) build system and codebase. The integration replaces the strstr-based JSON parsing in _parse_ai_response() with proper json-glib parsing, and adds comprehensive unit tests.
Current State Analysis
What Has Already Been Done
| Component | Status | Details |
|---|---|---|
configure.ac |
DONE | PKG_CHECK_MODULES([json-glib], [json-glib-1.0 >= 1.6.0]) added at line 101-102 |
src/ai/ai_client.c |
DONE | #include <json-glib/json-glib.h> added at line 24; _parse_ai_response() rewritten using json-glib |
Dockerfile.ubuntu |
DONE | libjson-glib-dev added at line 37 |
Dockerfile.debian |
DONE | libjson-glib-dev added at line 38 |
What Is Missing (Root Causes of bootstrap.sh Failure)
-
Makefile.ammissing json-glib flags:AM_CFLAGSat line 272 does not include$(json-glib_CFLAGS)tests_unittests_unittests_LDADDat line 299 does not include$(json-glib_LIBS)- The main
profanitybinary target also needs$(json-glib_LIBS)in its link flags
-
No unit tests for
_parse_ai_response():test_ai_client.chas 464 lines of tests but none for the JSON parsing function- The function is
static, so it cannot be tested directly; a test harness or refactoring is needed
-
bootstrap.shfailure:bootstrap.shis a simple script:mkdir -p m4 && autoreconf -i "$@"- The failure is caused by
autoreconffailing due to missing json-glib m4 macros in them4/directory, or theconfigure.acreferencingPKG_CHECK_MODULESwithout the properax_pthread.m4or json-glib pkg-config files being available in the build environment
Detailed Plan
1. Build System Changes
1.1 configure.ac — No Changes Needed
The json-glib check is already present:
PKG_CHECK_MODULES([json-glib], [json-glib-1.0 >= 1.6.0], [],
[AC_MSG_ERROR([json-glib 1.6.0 or higher is required])])
This generates the variables json-glib_CFLAGS and json-glib_LIBS for use in Makefile.am.
1.2 Makefile.am — Changes Required
File: Makefile.am
Change 1: Add json-glib_CFLAGS to AM_CFLAGS (line 272)
# Current (line 272):
AM_CFLAGS = @AM_CFLAGS@ -I$(srcdir)/src
# Change to:
AM_CFLAGS = @AM_CFLAGS@ $(json-glib_CFLAGS) -I$(srcdir)/src
Change 2: Add json-glib_LIBS to profanity linking (line 275)
The profanity binary target needs json-glib_LIBS. Since profanity_SOURCES is defined at line 275 and no explicit profanity_LDADD exists, we need to add one:
# Add after line 275:
profanity_LDADD = $(json-glib_LIBS) $(LIBS)
Change 3: Add json-glib_LIBS to test linking (line 299)
# Current (line 299):
tests_unittests_unittests_LDADD = -lcmocka
# Change to:
tests_unittests_unittests_LDADD = -lcmocka $(json-glib_LIBS)
1.3 Why bootstrap.sh Fails
The bootstrap.sh script runs autoreconf -i, which regenerates the configure script from configure.ac. The failure occurs because:
-
pkg-config dependency:
PKG_CHECK_MODULESrequirespkg-configto be available at configure-time (not build-time). Theautoreconfstep itself should succeed, but the resultingconfigurescript will fail ifpkg-config --modversion json-glib-1.0 >= 1.6.0cannot find the json-glib installation. -
Likely root cause: The build environment (Docker container or host) does not have
json-glibdevelopment files installed, orpkg-configcannot locate thejson-glib-1.0.pcfile.
Fix: Ensure libjson-glib-dev (Debian/Ubuntu) or json-glib (Arch/Fedora) is installed in the build environment before running bootstrap.sh.
2. Source Code Changes
2.1 src/ai/ai_client.c — No Changes Needed
The _parse_ai_response() function has already been rewritten using json-glib:
static gchar*
_parse_ai_response(const gchar* response_json)
{
// ... json-glib parsing with three fallback strategies:
// Try 1: Perplexity /v1/agent format
// Try 2: OpenAI /v1/chat/completions format
// Try 3: Fallback "text" field
}
2.2 src/ai/ai_client.h — No Changes Needed
The header file already includes <glib.h> and defines all necessary types. No json-glib-specific types are exposed (json-glib is an implementation detail).
3. Test Changes
3.1 tests/unittests/test_ai_client.c — New Tests Required
The current test file has 464 lines covering provider management, session handling, JSON escaping, and autocomplete. No tests exist for _parse_ai_response() because it is static.
Option A: Refactor _parse_ai_response to be testable (Recommended)
Make the function non-static and add a test wrapper:
// In ai_client.h, add:
gchar* ai_parse_ai_response(const gchar* response_json);
// In ai_client.c, change:
// static gchar* _parse_ai_response(...) → gchar* ai_parse_ai_response(...)
Option B: Use a test harness with extern declaration
Add to test file:
extern gchar* _parse_ai_response(const gchar* response_json);
Recommended tests to add:
| Test Name | Description |
|---|---|
test_ai_parse_response_null |
NULL input returns NULL |
test_ai_parse_response_empty |
Empty string returns NULL |
test_ai_parse_response_invalid_json |
Malformed JSON returns NULL |
test_ai_parse_response_openai_format |
Valid OpenAI /v1/chat/completions response |
test_ai_parse_response_openai_empty_choices |
Response with empty choices array |
test_ai_parse_response_perplexity_format |
Valid Perplexity /v1/agent response |
test_ai_parse_response_perplexity_empty_output |
Response with empty output array |
test_ai_parse_response_text_fallback |
Response with only "text" field |
test_ai_parse_response_unicode_content |
Content with unicode characters |
test_ai_parse_response_multiline_content |
Content with newlines and tabs |
test_ai_parse_response_html_content |
Content with HTML tags |
test_ai_parse_response_error_format |
Response with "error" field (not "choices") |
3.2 tests/unittests/test_ai_client.h — Update Required
Add declarations for new test functions:
/* JSON parsing tests */
void test_ai_parse_response_null(void** state);
void test_ai_parse_response_empty(void** state);
void test_ai_parse_response_invalid_json(void** state);
void test_ai_parse_response_openai_format(void** state);
void test_ai_parse_response_openai_empty_choices(void** state);
void test_ai_parse_response_perplexity_format(void** state);
void test_ai_parse_response_perplexity_empty_output(void** state);
void test_ai_parse_response_text_fallback(void** state);
void test_ai_parse_response_unicode_content(void** state);
void test_ai_parse_response_multiline_content(void** state);
void test_ai_parse_response_html_content(void** state);
void test_ai_parse_response_error_format(void** state);
3.3 tests/unittests/unittests.c — Update Required
Add new test entries after the existing AI client tests (around line 696):
// After line 696 (test_ai_json_escape_backslash_quote):
cmocka_unit_test(test_ai_parse_response_null),
cmocka_unit_test(test_ai_parse_response_empty),
cmocka_unit_test(test_ai_parse_response_invalid_json),
cmocka_unit_test(test_ai_parse_response_openai_format),
cmocka_unit_test(test_ai_parse_response_openai_empty_choices),
cmocka_unit_test(test_ai_parse_response_perplexity_format),
cmocka_unit_test(test_ai_parse_response_perplexity_empty_output),
cmocka_unit_test(test_ai_parse_response_text_fallback),
cmocka_unit_test(test_ai_parse_response_unicode_content),
cmocka_unit_test(test_ai_parse_response_multiline_content),
cmocka_unit_test(test_ai_parse_response_html_content),
cmocka_unit_test(test_ai_parse_response_error_format),
4. Dockerfile Changes
4.1 Dockerfile.ubuntu — No Changes Needed
libjson-glib-dev is already present at line 37.
4.2 Dockerfile.debian — No Changes Needed
libjson-glib-dev is already present at line 38.
4.3 Dockerfile.fedora — Check Required
Verify json-glib-devel is installed. If not, add:
json-glib-devel \
4.4 Dockerfile.arch — Check Required
Verify json-glib is installed. If not, add:
json-glib \
5. Bootstrap.sh Fix
5.1 Current State
#!/bin/sh
mkdir -p m4
autoreconf -i "$@"
5.2 Root Cause Analysis
The script itself is correct. The failure is due to one of:
- Missing
json-glib-1.0.pc:pkg-configcannot find json-glib in the build environment - Missing
m4/ax_pthread.m4: Theconfigure.acusesACX_PTHREADwhich requires theax_pthread.m4macro - Missing
m4/macros: Other autoconf macros referenced inconfigure.acare not present
5.3 Fix Steps
- Ensure json-glib-dev is installed in the build environment
- Verify m4 macros exist:
ls -la m4/ # Should contain: ax_pthread.m4, ax_valgrind_check.m4, etc. - If m4 macros are missing, they need to be copied from the system:
# For Debian/Ubuntu: cp /usr/share/autoconf-archive/m4/ax_pthread.m4 m4/ cp /usr/share/autoconf-archive/m4/ax_valgrind_check.m4 m4/ - Test bootstrap.sh manually:
./bootstrap.sh ./configure make
Implementation Order
graph TD
A[1. Fix Makefile.am] --> B[2. Verify bootstrap.sh works]
B --> C[3. Add test functions to test_ai_client.c]
C --> D[4. Update test_ai_client.h]
D --> E[5. Register tests in unittests.c]
E --> F[6. Verify Dockerfiles have json-glib-dev]
F --> G[7. Run make check to verify all tests pass]
Summary of Changes
| File | Change Type | Lines Affected |
|---|---|---|
Makefile.am |
Modify | Line 272 (AM_CFLAGS), Line 275 (add profanity_LDADD), Line 299 (LDADD) |
src/ai/ai_client.c |
None | Already complete |
src/ai/ai_client.h |
None | Already complete |
tests/unittests/test_ai_client.c |
Add | ~200 lines of new test functions |
tests/unittests/test_ai_client.h |
Add | ~12 new declarations |
tests/unittests/unittests.c |
Add | ~12 new test entries |
Dockerfile.ubuntu |
None | Already has libjson-glib-dev |
Dockerfile.debian |
None | Already has libjson-glib-dev |
Dockerfile.fedora |
Check | Verify json-glib-devel present |
Dockerfile.arch |
Check | Verify json-glib present |
bootstrap.sh |
Diagnose | Fix is environmental, not script change |
Verification Checklist
Makefile.amupdated with$(json-glib_CFLAGS)and$(json-glib_LIBS)bootstrap.shruns successfully./configurecompletes without json-glib errorsmakecompiles without errorsmake checkruns all tests including new json-glib tests- All existing tests still pass
- Docker builds succeed with json-glib integration