A learning project to understand C++, Python, networking, and the fundamentals of key-value databases.
A simple key-value store with:
- C++ server that stores data in memory ✓
- Python client to interact with the server ✓
- Text-based protocol for communication ✓
Think of it like a dictionary/hash map accessible over the network!
- Protocol specification defined (docs/protocol.md)
- C++ key-value storage class implemented
- C++ TCP server with network communication
- Protocol parser and command handling
- Full integration and testing
- Python client implementation
- Comprehensive test suite (pytest)
- Usage examples
- CI/CD pipeline (GitHub Actions)
- Code coverage reporting (Codecov)
- Multi-platform matrix testing (Ubuntu, macOS, Windows)
- Automated server management in tests
- C++ compiler with C++17 support (g++ 7+ or clang++ 5+)
- CMake 3.10 or higher
- Python 3.7+
- pytest (for running Python tests)
cd server mkdir build && cd build cmake .. make./serverThe server will start listening on port 8080.
From another terminal, connect using netcat:
nc localhost 8080Then try some commands:
SET username Alice OK GET username OK Alice EXISTS username OK 1 DELETE username OK GET username ERROR KEY_NOT_FOUND cd server/build ./test_kvstoreAll tests should pass ✓
Install dependencies:
pip3 install pytestBasic Usage:
from kvstore_client import KVStoreClient # Using context manager (recommended) with KVStoreClient('localhost', 8080) as client: client.set('username', 'Alice') value = client.get('username') print(value) # 'Alice' # Check if key exists if client.exists('username'): print("Key exists!") # Delete a key client.delete('username')Run Example Script:
# Make sure server is running first! cd client python3 example.pyRun Python Tests:
cd client # Run all tests (requires server running for integration tests) pytest test_kvstore_client.py -v # Run only unit tests (no server needed) pytest test_kvstore_client.py -m "not integration" -v # Run only integration tests (server must be running) pytest test_kvstore_client.py -m integration -vSimple text commands ending with \n:
Available Commands:
SET key value- Store a key-value pairGET key- Retrieve a valueDELETE key- Remove a key-value pairEXISTS key- Check if a key exists
Responses:
OK- Success (for SET, DELETE)OK value- Success with data (for GET)OK 1/OK 0- Boolean result (for EXISTS)ERROR KEY_NOT_FOUND- Key doesn't existERROR INVALID_COMMAND- Unknown commandERROR MISSING_ARGUMENTS- Missing required parameters
See docs/protocol.md for full details.
cpp-py-kvstore/ ├── docs/ │ └── protocol.md # Protocol specification ├── server/ # C++ server │ ├── CMakeLists.txt # Build configuration │ ├── src/ │ │ ├── main.cpp # Entry point │ │ ├── server.h/cpp # Network server │ │ ├── kvstore.h/cpp # Storage implementation │ │ └── test_kvstore.cpp # C++ tests │ └── build/ # Build output (gitignored) └── client/ # Python client ├── kvstore_client.py # Client library ├── example.py # Usage examples ├── test_kvstore_client.py # Test suite └── pytest.ini # Test configuration - Unit tests for
KVStoreclass - All core operations tested (set, get, delete, exists)
- Run with
./test_kvstorefromserver/build/
- 9 unit tests: Input validation and response parsing (mocked, no server needed)
- 5 integration tests: End-to-end testing with real C++ server
- Custom pytest markers for selective test execution
- Run with
pytest test_kvstore_client.py -vfromclient/
- Automated testing via GitHub Actions on every push and pull request
- Multi-platform matrix testing: Ubuntu, macOS, Windows
- Platform coverage:
- Ubuntu & macOS: Full testing (C++ + Python)
- Windows: Python client testing only (C++ server uses Unix APIs)
- Workflow steps:
- Build C++ server (Unix platforms)
- Run C++ tests
- Run Python unit tests with coverage
- Start server and run Python integration tests (Unix)
- Upload coverage to Codecov
- Automatic cleanup
- Status badge at top of README shows current build status
- View all test runs: Actions tab
- C++ programming: Classes, STL containers (
std::unordered_map),std::optional - Python programming: Context managers, logging, proper library design
- Socket programming: TCP sockets, client-server architecture
- Protocol design: Text-based communication protocols
- Testing: Unit tests, integration tests, mocking, pytest
- CI/CD: GitHub Actions, automated testing pipelines
- Memory management: RAII patterns, references vs pointers
- Build systems: CMake configuration
- Git workflows: Feature branches, pull requests, documentation
The server listens on all interfaces (0.0.0.0:8080), so you can connect from:
- Same machine:
nc localhost 8080or use Python client - Other machines on LAN: Connect using server's IP address
Note: You may need to allow port 8080 through your firewall:
# Red Hat/Fedora/CentOS sudo firewall-cmd --add-port=8080/tcp --permanent sudo firewall-cmd --reloadCurrent known limitations:
- Keys and values cannot contain spaces or newlines
- Single-threaded (handles one client at a time)
- No persistence (data lost when server stops)
- No authentication or encryption
- No maximum storage limits
- Integration tests require manual server startup locally (automated in CI)
These are acceptable for a learning project and may be addressed in future iterations.
Potential improvements for continued learning:
- Matrix testing (test on multiple OS: Ubuntu, macOS, Windows)
- Self-hosted RHEL runner for CI
- Code coverage reporting with badges
- Automated server lifecycle in local tests
- Multi-threaded server (handle concurrent clients)
- Data persistence (save to disk)
- Additional data structures (lists, sets)
- Performance benchmarking
This README grows with the project!