This document describes vissr's unit-test and fuzz-test infrastructure
as of the broad-coverage push landed alongside the stability/security
batches (commit ef639f0 plus PRs #119, #120, #121, #122 and the
present comprehensive-coverage PR).
go test ./...runs the entire test suite.
The paths to the different unit tests can be explicitly provided, enabling test of a reduced set of unit tests. Shown below are the paths to the complete set of unit tests as of 27-05-2026.
go test \
./utils \
./server/vissv2server \
./server/vissv2server/atServer \
./server/vissv2server/serviceMgr \
./server/vissv2server/mqttMgr \
./server/vissv2server/wsMgr \
./server/vissv2server/wsMgrFT \
./server/vissv2server/udsMgr \
./server/vissv2server/grpcMgr \
./server/agt_server \
./client/client-1.0/compress_client \
./client/client-1.0/csv_client \
./client/client-1.0/filetransfer_client \
./client/client-1.0/grpc_client \
./client/client-1.0/testClient \
./feeder/feeder-rl \
./feeder/feeder-template/feederv4 \
./feeder/feeder-evic \
./feeder/feeder-evic/evicSim
Tests for the mutex fixes shipped across the security batches
(WsClientIndexMu, sessionListMu, jtiCacheMu in atServer and
agt_server, udsClientIndexMu, grpcStateMu) are designed to fail
under go test -race if the mutex protecting their shared state is
removed. Run:
go test -race ./server/vissv2server/atServer \
./server/vissv2server/wsMgrFT \
./server/vissv2server/udsMgr \
./server/vissv2server/grpcMgr \
./server/agt_server \
./utilsNative Go fuzz harnesses cover parsers that consume attacker- controlled input. Run an individual fuzzer for ~30s:
go test -run='^$' -fuzz=FuzzValidateTransferName -fuzztime=30s \
./server/vissv2server/wsMgrFTRun all of them in turn (CI nightly):
fuzzers=(
'FuzzValidateTransferName ./server/vissv2server/wsMgrFT'
'FuzzSafeServerFilename ./client/client-1.0/filetransfer_client'
'FuzzEncodeDlRequest ./client/client-1.0/filetransfer_client'
'FuzzExtractKeyValue ./server/vissv2server/atServer'
'FuzzProcessHistoryCtrl ./server/vissv2server/serviceMgr'
'FuzzProcessHistoryGet ./server/vissv2server/serviceMgr'
'FuzzMapRequest ./utils'
'FuzzJsonSchemaValidate ./utils'
'FuzzGetFileDescriptorData ./server/vissv2server'
'FuzzGetRangeBoundaries ./server/vissv2server'
'FuzzGetValueForKey ./server/vissv2server/wsMgr'
'FuzzCompressTs ./server/vissv2server/wsMgr'
)
for entry in "${fuzzers[@]}"; do
set -- $entry
echo "==== $1 ===="
go test -run='^$' -fuzz="$1" -fuzztime=30s "$2" || exit 1
doneFailures land under testdata/fuzz/<FuzzerName>/. Commit any that
surface real bugs as part of the fix; the file then becomes a seed
corpus entry.
| Fix area | Test file |
|---|---|
validateTransferName path traversal (wsMgrFT) |
server/vissv2server/wsMgrFT/wsMgrFT_test.go |
getDataSessionIndex claim step + sessionListMu race |
server/vissv2server/wsMgrFT/wsMgrFT_test.go |
safeServerFilename client-side path traversal |
client/client-1.0/filetransfer_client/filetransfer_client_test.go |
extractKeyValue safe type-assert (atServer) |
server/vissv2server/atServer/atServer_fixes_test.go |
jtiCache mutex (atServer, agt_server) |
server/vissv2server/atServer/atServer_fixes_test.go, server/agt_server/agt_server_test.go |
AGT / AT / HTTP POST body limits (MaxBytesReader) |
server/agt_server/agt_server_test.go, server/vissv2server/atServer/atServer_fixes_test.go, utils/managerhandlers_test.go |
processHistoryCtrl panic + index + bufSize cap |
server/vissv2server/serviceMgr/serviceMgr_test.go |
processHistoryGet panic + index |
server/vissv2server/serviceMgr/serviceMgr_test.go |
activate/deactivateInterval ticker-leak |
server/vissv2server/serviceMgr/serviceMgr_test.go |
service manager handlers (handleServiceSet/Get/Subscribe/Unsubscribe, internal kill and cancel): a malformed request is an error response, not a panic |
server/vissv2server/serviceMgr/serviceMgr_assertions_test.go |
getBrokerSocket env-var / fallback / TLS (mqttMgr) |
server/vissv2server/mqttMgr/mqttMgr_test.go |
JsonSchemaValidate nil-deref guard |
utils/common_fixes_test.go |
WsClientIndexMu race |
utils/managerhandlers_test.go |
udsClientIndexMu race + -1 pool-exhaustion guard |
server/vissv2server/udsMgr/udsMgr_test.go |
grpcStateMu race |
server/vissv2server/grpcMgr/grpcMgr_test.go |
getFileDescriptorData type-assert (vissv2server) |
server/vissv2server/vissv2server_test.go |
TouchFile mode 0644 |
feeder/feeder-rl/feeder-rl_test.go |
onNotificationList lookup contract |
feeder/feeder-template/feederv4/feederv4_test.go |
| Area | Test file |
|---|---|
utils.IsNumber, IsBoolean predicates |
utils/common_broader_test.go |
utils.PathToUrl ⇄ UrlToPath round-trip |
utils/common_broader_test.go |
utils.GetMaxValidation |
utils/common_broader_test.go |
utils.ExtractRootName |
utils/common_broader_test.go |
utils.GenerateHmac / VerifyTokenSignature round-trip + tamper |
utils/common_broader_test.go |
utils.AddKeyValue no-Marshal value injection |
utils/common_broader_test.go |
utils.MapRequest fuzz |
utils/common_fixes_test.go |
wsMgr.getValueForKey, getSortedPaths, dcCache |
server/vissv2server/wsMgr/wsMgr_test.go |
| Helper | Test file |
|---|---|
extractMgrId (mgrId?clientId parser) |
server/vissv2server/vissv2server_helpers_test.go |
getPathLen (NUL-aware buffer length) |
server/vissv2server/vissv2server_helpers_test.go |
countPathSegments |
server/vissv2server/vissv2server_helpers_test.go |
getTokenErrorMessage (all indices) |
server/vissv2server/vissv2server_helpers_test.go |
setTokenErrorResponse |
server/vissv2server/vissv2server_helpers_test.go |
singleToDoubleQuote |
server/vissv2server/vissv2server_helpers_test.go |
extractNoScopeElementsLevel1 / Level2 |
server/vissv2server/vissv2server_helpers_test.go |
getTokenContext (safe defaults) |
server/vissv2server/vissv2server_helpers_test.go |
removeLocalProperty |
server/vissv2server/vissv2server_helpers_test.go |
getInternalFileName |
server/vissv2server/vissv2server_helpers_test.go |
calculateHash (SHA-1) |
server/vissv2server/vissv2server_helpers_test.go |
getRangeBoundary / getRangeBoundaries |
server/vissv2server/vissv2server_helpers_test.go |
FuzzGetRangeBoundaries |
server/vissv2server/vissv2server_helpers_test.go |
validateStructSetValue / verifyStruct (struct-typed SET values, against the real typedef.binary) |
server/vissv2server/vissv2server_struct_test.go |
| Helper | Test file |
|---|---|
registerRequest / routeResponse (entry released when the request is finished: get/set/discover, error responses, unsubscribe; kept while a subscription runs; no growth over many requests) |
server/vissv2server/mqttMgr/mqttMgr_topiclist_test.go |
mqttSubscribe (success, connect error, subscribe error, resubscribe after a reconnect), handleBrokerMessage, handleServerCoreMessage, runHub, MqttMgrInit end to end, with a mock MQTT.Client |
server/vissv2server/mqttMgr/mqttMgr_init_test.go |
MqttMgrInit wired to a model of the server core with separate request and response channels: concurrent requests all reach the core and are answered |
server/vissv2server/mqttMgr/mqttMgr_wiring_test.go |
transportDataSession (the real one): a response or event handed to a manager is never read back by the core as a request, however busy the manager is; requests still reach the core |
server/vissv2server/vissv2server_transport_test.go |
| Helper | Test file |
|---|---|
utils.WithRoutingInfo / AddRoutingForwardRequest: a client cannot set origin, RouterId, handle, gatingId or infoType; gRPC string injection |
utils/managerhandlers_origin_test.go |
the same through the server core: a protected signal is refused without a token when the client adds origin |
server/vissv2server/vissv2server_origin_test.go |
wsMgr::isKillSubscriptions: the schema check is skipped by the action, not by text in the request |
server/vissv2server/wsMgr/wsMgr_killcheck_test.go |
| Helper | Test file |
|---|---|
getDcConfig |
server/vissv2server/wsMgr/wsMgr_helpers_test.go |
setDcValue (pc + tsc parsing) |
server/vissv2server/wsMgr/wsMgr_helpers_test.go |
dcCacheInsert / getDcCacheIndex / resetDcCache / updatepayloadId lifecycle |
server/vissv2server/wsMgr/wsMgr_helpers_test.go |
signedTimeDiff |
server/vissv2server/wsMgr/wsMgr_helpers_test.go |
compressTs malformed-JSON rejection |
server/vissv2server/wsMgr/wsMgr_helpers_test.go |
getDpTsList (single / array / unknown) |
server/vissv2server/wsMgr/wsMgr_helpers_test.go |
FuzzGetValueForKey, FuzzCompressTs |
server/vissv2server/wsMgr/wsMgr_helpers_test.go |
| Helper | Test file |
|---|---|
getSubscriptionId (valid / missing / malformed JSON) |
server/vissv2server/grpcMgr/grpcMgr_helpers_test.go |
extractClientId (valid + malformed parse) |
server/vissv2server/grpcMgr/grpcMgr_helpers_test.go |
unsubscribe handling: updateRoutingList, killSubscribeStream, getSubscribeRoutingData / resetGrpcRoutingData guards, hub still serving after a subscribe + unsubscribe |
server/vissv2server/grpcMgr/grpcMgr_test.go |
| Client | Test file |
|---|---|
compress_client |
client/client-1.0/compress_client/compress_client_test.go |
csv_client |
client/client-1.0/csv_client/csv_client_test.go |
filetransfer_client |
client/client-1.0/filetransfer_client/filetransfer_client_helpers_test.go |
grpc_client |
client/client-1.0/grpc_client/grpc_client_test.go |
mqtt_client |
client/client-1.0/mqtt_client/mqtt_client_test.go |
mqtt_client (broker functions against a mock MQTT.Client, line reading, broker down in a child process) |
client/client-1.0/mqtt_client/mqtt_client_mock_test.go, mqtt_client_exit_test.go |
testClient |
client/client-1.0/testClient/testClient_test.go |
testClient MQTT part (mqttSubscribe, publishMessage, mqttTesterRun against a mock MQTT.Client, message classification, broker down in a child process) |
client/client-1.0/testClient/testClient_mqtt_mock_test.go, testClient_mqtt_exit_test.go |
Each covers the pure helpers in that client (path conversion, JSON parsing, request marshalling, file reading). Network-driven entry points are tested via runtest.sh integration.
| Feeder | Test file |
|---|---|
feeder-rl |
feeder/feeder-rl/feeder-rl_test.go (PR #122) |
feeder-template/feederv4 |
feeder/feeder-template/feederv4/feederv4_helpers_test.go |
feeder-template/feederv4 (storage writers: sqlite, redis, memcache) |
feeder/feeder-template/feederv4/feederv4_storage_test.go |
feeder-template/feederv4 (feederRegister) |
feeder/feeder-template/feederv4/feederv4_register_test.go |
feeder-template/feederv4 (random simulation, udsWriter) |
feeder/feeder-template/feederv4/feederv4_testability_test.go |
feeder-template/feederv4 (mongoSink) |
feeder/feeder-template/feederv4/mongosink_test.go |
feeder-evic |
feeder/feeder-evic/evicFeeder_test.go |
feeder-evic/evicSim |
feeder/feeder-evic/evicSim/evicSim_test.go |
Covers fileExists, deSerializeUInt (1/2/4-byte), inFeederScope,
splitToDomainDataAndTs, convertToDomainData, makeDataPoint,
calcInputValue, incDpIndex, enumConversion, linearConversion.
Where applicable these are also documented as TODO(testing): comments in the test files.
Listed here for visibility:
| Function | Why not testable | Refactor approach |
|---|---|---|
feederv4::newMongoSink |
Connects to and pings a live MongoDB (mongo.Connect, Ping). The sink itself (Write, writer, store) works against a one method updater interface and is tested with a fake collection; the pure helpers mongoTypedValue and mongoUpdateDoc are tested. |
Pass the connect function in, or cover it with an integration test against a MongoDB container (as CI does for the MQTT broker). |
feeder-evic::statestorageSet, initUdsEndpoint, initVSSInterfaceMgr, writeCanDriverLoop; feeder-evic and evicSim: initVehicleInterfaceMgr, initCanDriverInput / initCanDriverOutput, canDriverClient, serverSession, reDialer |
Coupled to live network / DB, or long-running loops. handleUdsConn (extracted from initUdsEndpoint) can be driven with net.Pipe but has no test yet. |
Same shape: inject interfaces, extract per-message handlers, extract a single-attempt helper from reDialer. |
filetransfer_client::initWebSocket*, controlClient, dataClient, downloadFile, uploadFile |
Need a running vissv2server. | Already integration-tested via runtest.sh. |
server/vissv2server/forest/— VSS-tree binary data files only.server/transport_sec/— TLS certs andtransportSec.jsonconfig only.client/client-1.0/Javascript/,transport_sec/— no Go code (JS client, certs, sample configs).
The repo's .gitignore has unanchored patterns feeder and
agt_server (lines 30, 53) that silently swallow any path with those
names — multiple test files in this PR and PR #122 needed
git add -f. The patterns should be anchored
(/feeder/feeder-template/feederv4/feeder for the actual built
binary, etc.) in a separate cleanup PR.
This test PR depends on PRs #119, #120, #121, and #122 being merged
first. The tests reference helpers and mutexes added across those
batches; without them, go test against this branch alone will not
build. Once the four prior PRs land, the full suite builds and
passes.