Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 121 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
run: |
sudo apt-get update -q
sudo apt-get install -y --no-install-recommends \
cmake ninja-build gcc
cmake ninja-build gcc g++

- name: Configure
run: |
Expand All @@ -34,9 +34,129 @@ jobs:
- name: Test
run: ctest --test-dir build --output-on-failure --parallel 4

- name: Verify shared test vectors are up to date
run: ./build/cpp/blob_vectors_gen | diff - tests/vectors/blob_vectors.json

- name: Upload test results on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: ctest-output
path: build/Testing/

cpp-standalone:
name: C++ Blob library (standalone cpp/)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get update -q
sudo apt-get install -y --no-install-recommends cmake ninja-build g++

- name: Configure, build & test the cpp/ package on its own
run: |
cmake -B build cpp -G Ninja -DMSGPACK_BUILD_TESTS=ON
cmake --build build --parallel
ctest --test-dir build --output-on-failure

python:
name: Python port
runs-on: ubuntu-latest
defaults:
run:
working-directory: python
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'

- name: Run tests
run: python -m unittest discover -s tests -v

js:
name: TypeScript / JS port
runs-on: ubuntu-latest
defaults:
run:
working-directory: js
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '24'

- name: Install dev dependencies
run: npm ci

- name: Type-check
run: npm run typecheck

- name: Build (emit dist/)
run: npm run build

- name: Run tests
run: npm test

rust:
name: Rust port
runs-on: ubuntu-latest
defaults:
run:
working-directory: rust
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt

- name: Format check
run: cargo fmt --check

- name: Clippy
run: cargo clippy --all-targets -- -D warnings

- name: Run tests
run: cargo test

go:
name: Go port
runs-on: ubuntu-latest
defaults:
run:
working-directory: go
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 'stable'

- name: Check formatting
run: |
unformatted="$(gofmt -l .)"
if [ -n "$unformatted" ]; then
echo "These files are not gofmt-clean:"
echo "$unformatted"
exit 1
fi

- name: Vet
run: go vet ./...

- name: Run tests
run: go test ./... -v
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,24 @@ build/
*.so
*.dSYM/
.DS_Store

# Node / TypeScript (js/)
node_modules/
js/dist/
*.tsbuildinfo

# Python (python/)
__pycache__/
*.py[cod]
*.egg-info/
.pytest_cache/
.mypy_cache/
python/dist/
python/build/

# Rust (rust/)
rust/target/
Cargo.lock

# Go (go/)
go/vendor/
46 changes: 13 additions & 33 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ project(sqlite_msgpack VERSION 1.5.0 LANGUAGES C CXX)
# ── Options ──────────────────────────────────────────────────────────────────
option(BUILD_SHARED_LIBS "Build msgpack as a loadable extension (.so/.dylib/.dll)" ON)
option(MSGPACK_BUILD_TESTS "Build and register CTest tests" ON)
option(MSGPACK_BUILD_FUZZ "Build libFuzzer-based fuzz harness" OFF)

# ── Compiler flags ────────────────────────────────────────────────────────────
# Suppress MSVC warnings about POSIX names and use of standard C library functions
Expand Down Expand Up @@ -80,12 +81,11 @@ target_include_directories(msgpack_static PRIVATE include)
target_compile_definitions(msgpack_static PRIVATE SQLITE_CORE)

# ── Standalone C++ MsgPack Blob library (no SQLite dependency) ─────────────────
add_library(msgpack_blob_static STATIC src/msgpack_blob.cpp)
target_include_directories(msgpack_blob_static PUBLIC include)
set_target_properties(msgpack_blob_static PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON)
if(NOT MSVC)
target_compile_options(msgpack_blob_static PRIVATE -Wall -Wextra)
endif()
# Lives in its own self-contained package under cpp/ (the C++ sibling of the
# python/, js/, rust/ and go/ ports). add_subdirectory makes the
# `msgpack_blob_static` target and its blob unit/corpus/vector-gen tests
# available to this top-level build; the interop test below reuses the target.
add_subdirectory(cpp)

# ── SQLite3 CLI shell ─────────────────────────────────────────────────────────
add_executable(sqlite3_cli src/shell.c src/sqlite3.c)
Expand Down Expand Up @@ -145,15 +145,11 @@ if(MSGPACK_BUILD_TESTS)
add_msgpack_test(msgpack_spec_p9 test_spec_p9_typed_primitives.c)
add_msgpack_test(msgpack_spec_p10 test_spec_p10_timestamp.c)

# C++ Blob API unit tests (standalone, no SQLite dependency)
add_executable(msgpack_blob_unit tests/test_msgpack_blob.cpp)
target_include_directories(msgpack_blob_unit PRIVATE include)
target_link_libraries(msgpack_blob_unit PRIVATE msgpack_blob_static)
set_target_properties(msgpack_blob_unit PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON)
add_test(NAME msgpack_blob_unit COMMAND msgpack_blob_unit)
set_tests_properties(msgpack_blob_unit PROPERTIES PASS_REGULAR_EXPRESSION "0 failed")
# C++ Blob API unit tests, the cross-language vector generator and the C++
# corpus runner live in cpp/CMakeLists.txt (built via add_subdirectory).

# C++ ↔ SQLite interop integration tests
# C++ ↔ SQLite interop integration tests (bridge the SQLite extension and the
# standalone Blob library, so this one stays at the top level).
add_executable(msgpack_interop tests/test_interop.cpp)
target_include_directories(msgpack_interop PRIVATE include)
target_compile_definitions(msgpack_interop PRIVATE SQLITE_CORE)
Expand All @@ -168,7 +164,7 @@ if(MSGPACK_BUILD_TESTS)
endif()

# ── Fuzz testing (requires Clang with libFuzzer support) ──────────────────────
option(MSGPACK_BUILD_FUZZ "Build libFuzzer-based fuzz harness" OFF)
# (MSGPACK_BUILD_FUZZ is declared in the options block near the top.)

if(MSGPACK_BUILD_FUZZ)
# Apply sanitizer flags to all targets so coverage instrumentation
Expand All @@ -181,13 +177,7 @@ if(MSGPACK_BUILD_FUZZ)
target_compile_options(fuzz_msgpack PRIVATE -fsanitize=fuzzer,address -g)
target_link_options(fuzz_msgpack PRIVATE -fsanitize=fuzzer,address)

# C++ API fuzz harness
add_executable(fuzz_msgpack_blob
tests/fuzz_msgpack_blob.cpp src/msgpack_blob.cpp)
target_include_directories(fuzz_msgpack_blob PRIVATE include)
set_target_properties(fuzz_msgpack_blob PROPERTIES CXX_STANDARD 17)
target_compile_options(fuzz_msgpack_blob PRIVATE -fsanitize=fuzzer,address -g)
target_link_options(fuzz_msgpack_blob PRIVATE -fsanitize=fuzzer,address)
# The C++ Blob API fuzz harness (fuzz_msgpack_blob) is defined in cpp/.
endif()

# ── Fuzz corpus runner (no libFuzzer needed — runs corpus files directly) ─────
Expand All @@ -205,17 +195,7 @@ if(MSGPACK_BUILD_TESTS)
COMMAND fuzz_corpus_runner ${CMAKE_SOURCE_DIR}/tests/fuzz_corpus)
set_tests_properties(fuzz_corpus PROPERTIES PASS_REGULAR_EXPRESSION "0 failed")

# C++ API corpus runner (no libFuzzer needed)
add_executable(fuzz_blob_corpus_runner
tests/fuzz_blob_corpus_runner.cpp tests/fuzz_msgpack_blob.cpp src/msgpack_blob.cpp)
target_include_directories(fuzz_blob_corpus_runner PRIVATE include)
set_target_properties(fuzz_blob_corpus_runner PROPERTIES CXX_STANDARD 17)
if(NOT MSVC)
target_compile_options(fuzz_blob_corpus_runner PRIVATE -w)
endif()
add_test(NAME fuzz_blob_corpus
COMMAND fuzz_blob_corpus_runner ${CMAKE_SOURCE_DIR}/tests/fuzz_corpus)
set_tests_properties(fuzz_blob_corpus PROPERTIES PASS_REGULAR_EXPRESSION "0 failed")
# The C++ API corpus runner (fuzz_blob_corpus_runner) is defined in cpp/.
endif()

# ── Install headers ───────────────────────────────────────────────────────────
Expand Down
22 changes: 13 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ your fix.

- **C code** (`src/msgpack.c`): follows the existing SQLite-adjacent style — 2-space
indent, `camelCase` locals, `snake_case` functions.
- **C++ code** (`src/msgpack_blob.cpp`, `include/msgpack_blob.hpp`): `snake_case`
- **C++ code** (`cpp/src/msgpack_blob_*.cpp`, `cpp/include/msgpack_blob.hpp`): `snake_case`
for methods and variables, `PascalCase` for types/enums, 4-space indent.
- Compiler warnings are the primary lint mechanism. The C++ library compiles
cleanly with `-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion`.
Expand All @@ -79,21 +79,25 @@ your fix.

```
include/
msgpack_blob.hpp C++ public header
sqlite3.h SQLite amalgamation header
src/
msgpack.c SQLite extension implementation
msgpack_blob.cpp Standalone C++ library
sqlite3.c SQLite amalgamation
cpp/ Standalone C++ Blob library (self-contained package)
include/msgpack_blob.hpp C++ public header
src/msgpack_blob_detail.hpp Shared private internals
src/msgpack_blob_{decode,encode,json,mutate,iterate}.cpp Library modules
tests/test_msgpack_blob.cpp C++ API unit tests
tests/fuzz_msgpack_blob.cpp libFuzzer harness (C++ API)
tests/gen_blob_vectors.cpp Cross-language test-vector generator
README.md C++ API reference
python/ js/ rust/ go/ Native ports of the Blob API (see each README)
tests/
test_msgpack.c C unit tests
test_msgpack_blob.cpp C++ API unit tests
test_interop.cpp C++ ↔ SQLite integration tests
fuzz_msgpack.c libFuzzer harness (SQL extension)
fuzz_msgpack_blob.cpp libFuzzer harness (C++ API)
fuzz_corpus/ Seed corpus files
docs/
cpp-api.md C++ API reference
fuzz_corpus/ Seed corpus files (shared)
vectors/blob_vectors.json Shared cross-language test vectors
```

## Submitting changes
Expand All @@ -102,7 +106,7 @@ docs/
2. Make your changes — keep commits focused and well-described.
3. Ensure all tests pass: `cd build && ctest --output-on-failure`
4. If you add new functionality, add corresponding tests.
5. If you change the public API, update `docs/cpp-api.md` and/or `README.md`.
5. If you change the public API, update `cpp/README.md` and/or `README.md`.
6. Open a pull request with a clear description of what and why.

## Byte-identical encoding
Expand Down
Loading
Loading