You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Line coverage flatters these two packages; branch coverage does not. From the merged solution run (3556 tests, all green):
package
lines
branches
Abblix.Oidc.Server.Vault
91.9%
51.9% (80/154)
Abblix.Oidc.Server.Azure
78.5%
45.9% (45/98)
Every other production project sits between 71% and 89% on branches. These two are the outliers, and they are the two that talk to an external custodian over the network.
A line is counted as covered when it runs once. A line like if (properties.Enabled != true) therefore reads as covered while only the true side has ever been taken. That is the whole gap here: the happy path runs, the answers-we-do-not-like do not.
Reproduce with dotnet test Abblix.Oidc.slnx -c Debug --coverage --coverage-output-format cobertura, then read condition-coverage per line rather than the line hits.
Where the untaken branches are
Almost all of them sit in the two classes that speak to the backend:
Vault/TransitCustodian.cs - 62 of the package's 74 missed branches
Azure/KeyVaultClient.cs - 48 of the package's 53
The rest is a handful in ApiResponse.cs, KeyValueStore.cs, Transport.cs, BlobKeyRingStore.cs and ServiceCollectionExtensions.cs.
They fall into two kinds, and the second kind is the one that matters.
Algorithm mapping switches, one arm walked
TransitCustodian.cs:120 and :135 - the algorithm and hash-algorithm switches
TransitCustodian.cs:254 - the RSA key-family check
KeyVaultClient.cs:120 and :165 - MapSignatureAlgorithm and MapEncryptionAlgorithm
Cheap to close with a theory over the algorithm names. No backend needed. Worth doing because a wrong arm here means signing with an algorithm the caller did not ask for, and the mistake is invisible until a verifier elsewhere rejects the result.
Guards on an answer we do not like
KeyVaultClient.cs:197 - if (properties.Enabled != true). Disabling a key in Key Vault is how an operator revokes a compromised key. The branch that honours that has never been taken. If it is wrong, revocation silently does not revoke, and nothing in the suite would say so.
KeyVaultClient.cs:261 - if (separator <= 0 || separator == keyId.Length - 1), the malformed key-identifier guard.
KeyVaultClient.cs:103 - the credential-configuration check.
The remaining untaken branches in ApiResponse.cs, Transport.cs and KeyValueStore.cs are the backend-said-no paths.
Proposal
Cover the mapping switches with theories. Mechanical, no infrastructure, closes the bulk of the count.
Cover the guards with a stub custodian that answers badly: a disabled key, a malformed identifier, a rejected credential, a transport failure. These are the branches an operator's real actions reach, so a test here defends behaviour rather than a number.
Verify the disabled-key path against a live backend. There is an OpenBao container in the loop already and Azurite for the Azure side; a unit test with a stub proves the branch is wired, a live one proves the backend actually reports what the branch expects. Both, not either.
Both packages exist to keep a private key inside an HSM or KMS. The interesting behaviour of such a client is not what it does when the custodian cooperates - it is what it does when the custodian refuses, returns a disabled key, or cannot be reached. That is precisely the half that is currently untested.
Acceptance
Branch coverage in both packages in line with the rest of the solution.
The disabled-key path covered by a unit test and confirmed against a live backend.
Every algorithm arm of every mapping switch exercised.
Measurement
Line coverage flatters these two packages; branch coverage does not. From the merged solution run (3556 tests, all green):
Abblix.Oidc.Server.VaultAbblix.Oidc.Server.AzureEvery other production project sits between 71% and 89% on branches. These two are the outliers, and they are the two that talk to an external custodian over the network.
A line is counted as covered when it runs once. A line like
if (properties.Enabled != true)therefore reads as covered while only thetrueside has ever been taken. That is the whole gap here: the happy path runs, the answers-we-do-not-like do not.Reproduce with
dotnet test Abblix.Oidc.slnx -c Debug --coverage --coverage-output-format cobertura, then readcondition-coverageper line rather than the line hits.Where the untaken branches are
Almost all of them sit in the two classes that speak to the backend:
Vault/TransitCustodian.cs- 62 of the package's 74 missed branchesAzure/KeyVaultClient.cs- 48 of the package's 53The rest is a handful in
ApiResponse.cs,KeyValueStore.cs,Transport.cs,BlobKeyRingStore.csandServiceCollectionExtensions.cs.They fall into two kinds, and the second kind is the one that matters.
Algorithm mapping switches, one arm walked
TransitCustodian.cs:120and:135- the algorithm and hash-algorithm switchesTransitCustodian.cs:254- the RSA key-family checkKeyVaultClient.cs:120and:165-MapSignatureAlgorithmandMapEncryptionAlgorithmCheap to close with a theory over the algorithm names. No backend needed. Worth doing because a wrong arm here means signing with an algorithm the caller did not ask for, and the mistake is invisible until a verifier elsewhere rejects the result.
Guards on an answer we do not like
KeyVaultClient.cs:197-if (properties.Enabled != true). Disabling a key in Key Vault is how an operator revokes a compromised key. The branch that honours that has never been taken. If it is wrong, revocation silently does not revoke, and nothing in the suite would say so.KeyVaultClient.cs:261-if (separator <= 0 || separator == keyId.Length - 1), the malformed key-identifier guard.KeyVaultClient.cs:103- the credential-configuration check.ApiResponse.cs,Transport.csandKeyValueStore.csare the backend-said-no paths.Proposal
obj/**/LoggerMessage.g.cscontributes untaken branches in both packages and nothing a human can act on. Same measurement noise as Mvc adapter coverage: opt-in endpoints are never walked end to end #274.Why this is not "raise the number"
Both packages exist to keep a private key inside an HSM or KMS. The interesting behaviour of such a client is not what it does when the custodian cooperates - it is what it does when the custodian refuses, returns a disabled key, or cannot be reached. That is precisely the half that is currently untested.
Acceptance