[client] pqkem: cover the env flags, signal port, offer marker and status flag

These branches decide whether ML-KEM runs, which port a peer is reached
on, and what the status reports, and none of them had a test.
This commit is contained in:
riccardom
2026-10-20 17:53:03 +02:00
parent aa9141c451
commit fb6e955f00
3 changed files with 124 additions and 0 deletions
+31
View File
@@ -164,3 +164,34 @@ func TestConn_RecoverPQKeyOverSignalOnlyWhenConnected(t *testing.T) {
c.RecoverPQKeyOverSignal()
assert.True(t, offerAttempted(hook), "a connected peer must get a recovery offer")
}
// TestConn_QuantumResistant covers the status flag: Rosenpass counts only when both sides
// run it, and an established ML-KEM PSK counts on its own.
func TestConn_QuantumResistant(t *testing.T) {
localRP := []byte("local-rosenpass-key")
remoteRP := []byte("remote-rosenpass-key")
cases := []struct {
name string
localRP []byte
remoteRP []byte
pqEstablished bool
want bool
}{
{"nothing", nil, nil, false, false},
{"rosenpass on both sides", localRP, remoteRP, false, true},
{"rosenpass only locally", localRP, nil, false, false},
{"rosenpass only remotely", nil, remoteRP, false, false},
{"ml-kem established", nil, nil, true, true},
{"ml-kem established, rosenpass only remotely", nil, remoteRP, true, true},
{"ml-kem established, rosenpass on both sides", localRP, remoteRP, true, true},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
conn := &Conn{config: ConnConfig{RosenpassConfig: RosenpassConfig{PubKey: c.localRP}}}
assert.Equal(t, c.want, conn.quantumResistant(c.remoteRP, c.pqEstablished),
"local rosenpass %t, remote rosenpass %t, ml-kem %t",
c.localRP != nil, c.remoteRP != nil, c.pqEstablished)
})
}
}
+58
View File
@@ -0,0 +1,58 @@
package pqkem
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestEnvFlags(t *testing.T) {
cases := []struct {
value string
want bool
}{
{"", false},
{"on", true},
{"ON", true},
{" on ", true},
{"off", false},
{"Off", false},
{"true", true},
{"TRUE", true},
{"1", true},
{"t", true},
{"false", false},
{"0", false},
{" 1 ", true},
{"yes", false},
{"garbage", false},
}
flags := []struct {
env string
get func() bool
}{
{EnvEnabled, Enabled},
{EnvStrict, Strict},
}
for _, f := range flags {
for _, c := range cases {
t.Run(f.env+"="+c.value, func(t *testing.T) {
t.Setenv(f.env, c.value)
assert.Equal(t, c.want, f.get(), "%s=%q", f.env, c.value)
})
}
}
}
func TestEnvFlagsUnset(t *testing.T) {
for _, env := range []string{EnvEnabled, EnvStrict} {
t.Setenv(env, "")
require.NoError(t, os.Unsetenv(env))
}
assert.False(t, Enabled(), "an unset %s must leave ML-KEM disabled", EnvEnabled)
assert.False(t, Strict(), "an unset %s must leave strict mode off", EnvStrict)
}
+35
View File
@@ -0,0 +1,35 @@
package internal
import (
"math"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
sProto "github.com/netbirdio/netbird/shared/signal/proto"
)
func signalOfferWithMlkemPort(port uint32) *sProto.Message {
return &sProto.Message{Body: &sProto.Body{
Type: sProto.Body_OFFER,
Payload: "ufrag:pwd",
MlkemPort: &port,
}}
}
// TestConvertToOfferAnswer_MlkemPort checks that the proto's 32-bit ML-KEM port is narrowed
// to uint16 only when it fits: a larger value is a malformed message, not a port to
// truncate.
func TestConvertToOfferAnswer_MlkemPort(t *testing.T) {
for _, port := range []uint32{0, 51833, math.MaxUint16} {
oa, err := convertToOfferAnswer(signalOfferWithMlkemPort(port))
require.NoError(t, err, "port %d", port)
assert.Equal(t, uint16(port), oa.MlkemPort, "port %d must survive the conversion", port)
}
for _, port := range []uint32{math.MaxUint16 + 1, math.MaxUint32} {
_, err := convertToOfferAnswer(signalOfferWithMlkemPort(port))
assert.Error(t, err, "port %d does not fit in uint16 and must be rejected", port)
}
}