- Added mock_lseek declaration and implementation for Linux
- Added mock_SetFilePointer declaration and implementation for Windows
- Added sys_lseek and sys_SetFilePointer macros for both BUILD_TEST and production modes
- Mocks follow existing pattern: validate descriptors, check type, forward to real functions
- Both mocks properly handle error cases and set errno/SetLastError
Add mock implementation for MoveFileExW Windows API function following
the existing pattern in the codebase. The mock forwards calls to the
real Windows API, allowing for future interception in the simulation
framework if needed.
Added mock implementations for file/directory search operations to
support both Windows and Linux in the simulation environment.
Windows mocks:
- FindFirstFileA: Wraps real search handle in descriptor
- FindNextFileA: Forwards to real API
- FindClose: Properly cleans up search handles
Linux mocks:
- opendir: Wraps real DIR* handle in descriptor
- readdir: Forwards to real API
- closedir: Properly cleans up directory handles
Common changes:
- Added DESC_DIRECTORY descriptor type to track directory handles
- Added real_d field to Descriptor for directory handles (HANDLE on Windows, DIR* on Linux)
- Updated close_desc to handle directory cleanup on both platforms
- Added sys_* macros for both BUILD_TEST and non-BUILD_TEST modes
- Added <dirent.h> include for Linux directory operations
Changes:
- Added is_nonblocking flag to Descriptor structure in system.c
- Implemented mock_fcntl (Linux) and mock_ioctlsocket (Windows) to handle setting sockets as non-blocking
- Set all sockets as non-blocking in tcp.c:
- Listen sockets in create_listen_socket()
- Accepted sockets in tcp_translate_events()
- Connecting sockets in tcp_connect()
- Added checks in mock_accept(), mock_recv(), and mock_send() to abort the simulation if a socket would block but is not configured as non-blocking
- This ensures proper non-blocking socket configuration and helps catch blocking socket errors during simulation
Added a simulation client that can run inside the TinyDFS simulation
framework, enabling fully deterministic end-to-end testing of the
distributed file system.
**New Files:**
- src/simulation_client.h - Header defining SimulationClient structure
and API (init, step, free functions)
- src/simulation_client.c - Implementation of simulation client with
test operations (create dir, create file, write, read, list, delete)
**Key Changes:**
**System Framework (src/system.c):**
- Added ProcessType enum (METADATA_SERVER, CHUNK_SERVER, CLIENT)
to distinguish different simulated process types
- Extended Process union to include SimulationClient
- Modified spawn_simulated_process() to detect --client flag and
initialize client processes using simulation_client_init()
- Updated update_simulation() to call simulation_client_step() for
client processes, handling timeout management
- Fixed cleanup_simulation() to properly set current_process before
freeing, preventing NULL pointer dereferences in mock_close()
- Added simulated_time static variable (struct timespec) for
deterministic clock mocking
- Added helper function is_client() to detect client processes
**API Updates (src/system.h):**
- Exported startup_simulation() function for proper initialization
- Added function declarations for simulation management
**Test Updates (src/main_test.c):**
- Added startup_simulation() call for proper initialization
- Spawns simulation client process with "--client" flag
- Increased iteration limit to 100,000 to allow operations to complete
- Added progress logging every 10,000 iterations
- Added explicit error checking and debug output
**Simulation Client Features:**
- Non-blocking operation model using tinydfs_isdone() and
tinydfs_process_events()
- State machine for sequential test operations
- Comprehensive test scenario:
1. Create directory (/test_dir)
2. Create file (/test_dir/test_file.txt)
3. Write data to file
4. Read data back
5. List directory contents
6. Delete file
- Proper integration with TinyDFS client library
- Returns poll descriptors from tinydfs_process_events()
- Timeout management for simulation scheduling
**Bug Fixes:**
- Fixed missing return statement in spawn_simulated_process()
- Fixed NULL pointer dereference in cleanup by setting current_process
- Added missing stdlib.h include for atoi()
The simulation client successfully initializes and integrates into the
simulation loop, demonstrating the framework's ability to run client
code deterministically alongside servers.
Implemented Windows high-resolution timing mocks for deterministic simulation:
**mock_QueryPerformanceCounter:**
- Returns deterministic counter based on simulated_time
- Uses fixed 10 MHz frequency (10,000,000 counts/second)
- Calculation: count = (tv_sec * freq) + (tv_nsec * freq / 1e9)
- Validates NULL pointer with ERROR_INVALID_PARAMETER
- Provides consistent, reproducible timing across test runs
**mock_QueryPerformanceFrequency:**
- Returns fixed frequency of 10 MHz (10,000,000 Hz)
- Common frequency on modern Windows systems
- Ensures deterministic behavior (no variation between runs)
- Validates NULL pointer with ERROR_INVALID_PARAMETER
**Integration:**
- Added function declarations to system.h
- Macros already existed (sys_QueryPerformanceCounter/Frequency)
- Complements existing mock_clock_gettime on Linux
- Both platforms now have deterministic high-resolution timing
This ensures Windows code using QueryPerformanceCounter for timing,
benchmarking, or rate limiting behaves deterministically in tests.
The fixed 10 MHz frequency provides nanosecond-level precision
(100ns per tick) suitable for most timing needs.