Implement issue 161: Add unit tests for read_multi_modal tool

- Add test_tool_read_multi_modal.sh with tests for:
  - Successfully reading a PNG image file
  - Error handling for non-existent files
  - Reading a JPG file (different MIME type)

- Fix json_types.hpp to properly serialize std::optional and std::variant
  types by adding serialize_to_json() helper function that dispatches to
  the correct serialization method.

- Register new test in tests/CMakeLists.txt
This commit is contained in:
2026-06-15 22:02:58 +00:00
parent 0020669eb0
commit 2824b89643
3 changed files with 99 additions and 1 deletions
+22 -1
View File
@@ -244,8 +244,29 @@ struct json_to_impl<std::variant<Alternatives...>> {
nlohmann_json_t.field = std::move(nlohmann_json_field_result.value()); \
}
// Helper to serialize a value to nlohmann::json
// Handles std::optional, std::variant, and primitive types
template<typename T>
nlohmann::json serialize_to_json(const T& value) {
return value; // Works for primitives via implicit conversion
}
template<typename T>
nlohmann::json serialize_to_json(const std::optional<T>& opt) {
nlohmann::json j;
::to_json(j, opt);
return j;
}
template<typename... Alternatives>
nlohmann::json serialize_to_json(const std::variant<Alternatives...>& v) {
nlohmann::json j;
::to_json(j, v);
return j;
}
// to_json using nlohmann's existing pattern
#define DRH_JSON_TO(field) nlohmann_json_j[#field] = nlohmann_json_t.field;
#define DRH_JSON_TO(field) nlohmann_json_j[#field] = serialize_to_json(nlohmann_json_t.field);
// The main macro - generates to_json and json_to<Type>() template specialization
#define DRH_DEFINE_TYPE_REQUIRED(Type, ...) \
+1
View File
@@ -19,6 +19,7 @@ add_dr_test(test_tool_read_file)
add_dr_test(test_tool_list_files)
add_dr_test(test_tool_grep)
add_dr_test(test_tool_shell)
add_dr_test(test_tool_read_multi_modal)
# Add feature validation tests
add_dr_test(test_tool_restrictions)
+76
View File
@@ -0,0 +1,76 @@
#!/bin/bash
# test_tool_read_multi_modal.sh - Tests for read_multi_modal tool
# Create a minimal 1x1 PNG file for testing
printf '\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53\xDE\x00\x00\x00\x0C\x49\x44\x41\x54\x08\xD7\x63\xF8\xCF\xC0\x00\x00\x03\x01\x01\x00\x18\xDD\x8D\xB4\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82' > test_image.png
# Test 1: Successfully read a valid image file
# Mock response: ask for read_multi_modal
tool_call read_multi_modal '{"path":"test_image.png"}' >> mock_responses.txt
be_done 'Read complete' >> mock_responses.txt
OUTPUT=$("${DRHARNESS}" -F chat.json -n -m "Read image" -t read_multi_modal -d < "mock_responses.txt" 2>/dev/null)
if [ "${OUTPUT}" != "Read complete" ]; then
echo "FAIL: read_multi_modal tool - expected 'Read complete', got '${OUTPUT}'"
exit 1
fi
# Verify tool result is stored as an array (Content with vector<ContentPart>)
CONTENT_TYPE=$(dr_content_type chat.json 2)
if [ "$CONTENT_TYPE" != "array" ]; then
echo "FAIL: Expected tool result content to be an array, got '${CONTENT_TYPE}'"
exit 1
fi
# Verify the content part type is image_url
PART_TYPE=$(dr_content_part_type chat.json 2 0)
if [ "$PART_TYPE" != "image_url" ]; then
echo "FAIL: Expected content part type to be 'image_url', got '${PART_TYPE}'"
exit 1
fi
# Verify the image URL is a valid PNG data URI
IMAGE_URL=$(dr_content_part_image_url chat.json 2 0)
if ! echo "$IMAGE_URL" | grep -q "^data:image/png;base64,"; then
echo "FAIL: Expected image URL to be PNG data URI, got '${IMAGE_URL}'"
exit 1
fi
# Test 2: Error handling for non-existent file
rm -f chat.json
tool_call read_multi_modal '{"path":"nonexistent_image.png"}' >> mock_responses2.txt
be_done 'Error handled' >> mock_responses2.txt
"${DRHARNESS}" -F chat.json -n -m "Read nonexistent" -t read_multi_modal -d < "mock_responses2.txt" >/dev/null 2>&1
# Verify tool result is a string error message
CONTENT_TYPE=$(dr_content_type chat.json 2)
if [ "$CONTENT_TYPE" != "string" ]; then
echo "FAIL: Expected error content to be a string, got '${CONTENT_TYPE}'"
exit 1
fi
RESULT=$(dr_result chat.json 2)
if ! echo "$RESULT" | grep -q "Failed to read image"; then
echo "FAIL: Expected error message about failed image read, got '${RESULT}'"
exit 1
fi
# Test 3: Read a JPG file (different MIME type)
printf '\xFF\xD8\xFF\xE0\x00\x10JFIF' > test_image.jpg
rm -f chat.json
tool_call read_multi_modal '{"path":"test_image.jpg"}' >> mock_responses3.txt
be_done 'JPG read complete' >> mock_responses3.txt
"${DRHARNESS}" -F chat.json -n -m "Read JPG" -t read_multi_modal -d < "mock_responses3.txt" >/dev/null 2>&1
# Verify the image URL is a valid JPEG data URI
IMAGE_URL=$(dr_content_part_image_url chat.json 2 0)
if ! echo "$IMAGE_URL" | grep -q "^data:image/jpeg;base64,"; then
echo "FAIL: Expected image URL to be JPEG data URI, got '${IMAGE_URL}'"
exit 1
fi
echo "PASS: tool_read_multi_modal"