Files
netbird/client/internal/updater/reposign/signature_test.go
Zoltan Papp fe9b844511 [client] refactor auto update workflow (#5448)
Auto-update logic moved out of the UI into a dedicated updatemanager.Manager service that runs in the connection layer. The
UI no longer polls or checks for updates independently.
The update manager supports three modes driven by the management server's auto-update policy:
No policy set by mgm: checks GitHub for the latest version and notifies the user (previous behavior, now centralized)
mgm enforces update: the "About" menu triggers installation directly instead of just downloading the file — user still initiates the action
mgm forces update: installation proceeds automatically without user interaction
updateManager lifecycle is now owned by daemon, giving the daemon server direct control via a new TriggerUpdate RPC
Introduces EngineServices struct to group external service dependencies passed to NewEngine, reducing its argument count from 11 to 4
2026-03-13 17:01:28 +01:00

278 lines
6.7 KiB
Go

package reposign
import (
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParseSignature_Valid(t *testing.T) {
timestamp := time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC)
keyID, err := ParseKeyID("0123456789abcdef")
require.NoError(t, err)
signatureData := []byte{0x01, 0x02, 0x03, 0x04}
jsonData, err := json.Marshal(Signature{
Signature: signatureData,
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "blake2s",
})
require.NoError(t, err)
sig, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.NotNil(t, sig)
assert.Equal(t, signatureData, sig.Signature)
assert.Equal(t, timestamp.Unix(), sig.Timestamp.Unix())
assert.Equal(t, keyID, sig.KeyID)
assert.Equal(t, "ed25519", sig.Algorithm)
assert.Equal(t, "blake2s", sig.HashAlgo)
}
func TestParseSignature_InvalidJSON(t *testing.T) {
invalidJSON := []byte(`{invalid json}`)
sig, err := ParseSignature(invalidJSON)
assert.Error(t, err)
assert.Nil(t, sig)
}
func TestParseSignature_EmptyData(t *testing.T) {
emptyJSON := []byte(`{}`)
sig, err := ParseSignature(emptyJSON)
require.NoError(t, err)
assert.NotNil(t, sig)
assert.Empty(t, sig.Signature)
assert.True(t, sig.Timestamp.IsZero())
assert.Equal(t, KeyID{}, sig.KeyID)
assert.Empty(t, sig.Algorithm)
assert.Empty(t, sig.HashAlgo)
}
func TestParseSignature_MissingFields(t *testing.T) {
// JSON with only some fields
partialJSON := []byte(`{
"signature": "AQIDBA==",
"algorithm": "ed25519"
}`)
sig, err := ParseSignature(partialJSON)
require.NoError(t, err)
assert.NotNil(t, sig)
assert.NotEmpty(t, sig.Signature)
assert.Equal(t, "ed25519", sig.Algorithm)
assert.True(t, sig.Timestamp.IsZero())
}
func TestSignature_MarshalUnmarshal_Roundtrip(t *testing.T) {
timestamp := time.Date(2024, 6, 20, 14, 45, 30, 0, time.UTC)
keyID, err := ParseKeyID("fedcba9876543210")
require.NoError(t, err)
original := Signature{
Signature: []byte{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe},
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "sha512",
}
// Marshal
jsonData, err := json.Marshal(original)
require.NoError(t, err)
// Unmarshal
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
// Verify
assert.Equal(t, original.Signature, parsed.Signature)
assert.Equal(t, original.Timestamp.Unix(), parsed.Timestamp.Unix())
assert.Equal(t, original.KeyID, parsed.KeyID)
assert.Equal(t, original.Algorithm, parsed.Algorithm)
assert.Equal(t, original.HashAlgo, parsed.HashAlgo)
}
func TestSignature_NilSignatureBytes(t *testing.T) {
timestamp := time.Now().UTC()
keyID, err := ParseKeyID("0011223344556677")
require.NoError(t, err)
sig := Signature{
Signature: nil,
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "blake2s",
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.Nil(t, parsed.Signature)
}
func TestSignature_LargeSignature(t *testing.T) {
timestamp := time.Now().UTC()
keyID, err := ParseKeyID("aabbccddeeff0011")
require.NoError(t, err)
// Create a large signature (64 bytes for ed25519)
largeSignature := make([]byte, 64)
for i := range largeSignature {
largeSignature[i] = byte(i)
}
sig := Signature{
Signature: largeSignature,
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "blake2s",
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.Equal(t, largeSignature, parsed.Signature)
}
func TestSignature_WithDifferentHashAlgorithms(t *testing.T) {
tests := []struct {
name string
hashAlgo string
}{
{"blake2s", "blake2s"},
{"sha512", "sha512"},
{"sha256", "sha256"},
{"empty", ""},
}
keyID, err := ParseKeyID("1122334455667788")
require.NoError(t, err)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sig := Signature{
Signature: []byte{0x01, 0x02},
Timestamp: time.Now().UTC(),
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: tt.hashAlgo,
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.Equal(t, tt.hashAlgo, parsed.HashAlgo)
})
}
}
func TestSignature_TimestampPrecision(t *testing.T) {
// Test that timestamp preserves precision through JSON marshaling
timestamp := time.Date(2024, 3, 15, 10, 30, 45, 123456789, time.UTC)
keyID, err := ParseKeyID("8877665544332211")
require.NoError(t, err)
sig := Signature{
Signature: []byte{0xaa, 0xbb},
Timestamp: timestamp,
KeyID: keyID,
Algorithm: "ed25519",
HashAlgo: "blake2s",
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
// JSON timestamps typically have second or millisecond precision
// so we check that at least seconds match
assert.Equal(t, timestamp.Unix(), parsed.Timestamp.Unix())
}
func TestParseSignature_MalformedKeyID(t *testing.T) {
// Test with a malformed KeyID field
malformedJSON := []byte(`{
"signature": "AQID",
"timestamp": "2024-01-15T10:30:00Z",
"key_id": "invalid_keyid_format",
"algorithm": "ed25519",
"hash_algo": "blake2s"
}`)
// This should fail since "invalid_keyid_format" is not a valid KeyID
sig, err := ParseSignature(malformedJSON)
assert.Error(t, err)
assert.Nil(t, sig)
}
func TestParseSignature_InvalidTimestamp(t *testing.T) {
// Test with an invalid timestamp format
invalidTimestampJSON := []byte(`{
"signature": "AQID",
"timestamp": "not-a-timestamp",
"key_id": "0123456789abcdef",
"algorithm": "ed25519",
"hash_algo": "blake2s"
}`)
sig, err := ParseSignature(invalidTimestampJSON)
assert.Error(t, err)
assert.Nil(t, sig)
}
func TestSignature_ZeroKeyID(t *testing.T) {
// Test with a zero KeyID
sig := Signature{
Signature: []byte{0x01, 0x02, 0x03},
Timestamp: time.Now().UTC(),
KeyID: KeyID{},
Algorithm: "ed25519",
HashAlgo: "blake2s",
}
jsonData, err := json.Marshal(sig)
require.NoError(t, err)
parsed, err := ParseSignature(jsonData)
require.NoError(t, err)
assert.Equal(t, KeyID{}, parsed.KeyID)
}
func TestParseSignature_ExtraFields(t *testing.T) {
// JSON with extra fields that should be ignored
jsonWithExtra := []byte(`{
"signature": "AQIDBA==",
"timestamp": "2024-01-15T10:30:00Z",
"key_id": "0123456789abcdef",
"algorithm": "ed25519",
"hash_algo": "blake2s",
"extra_field": "should be ignored",
"another_extra": 12345
}`)
sig, err := ParseSignature(jsonWithExtra)
require.NoError(t, err)
assert.NotNil(t, sig)
assert.NotEmpty(t, sig.Signature)
assert.Equal(t, "ed25519", sig.Algorithm)
assert.Equal(t, "blake2s", sig.HashAlgo)
}