Files
Reloader/internal/pkg/reload/hasher_test.go
T

280 lines
5.9 KiB
Go

package reload
import (
"testing"
corev1 "k8s.io/api/core/v1"
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
)
func TestHasher_HashConfigMap(t *testing.T) {
hasher := NewHasher()
tests := []struct {
name string
cm *corev1.ConfigMap
wantHash string
}{
{
name: "empty configmap",
cm: &corev1.ConfigMap{
Data: nil,
BinaryData: nil,
},
wantHash: hasher.HashConfigMap(&corev1.ConfigMap{}),
},
{
name: "configmap with data",
cm: &corev1.ConfigMap{
Data: map[string]string{
"key1": "value1",
"key2": "value2",
},
},
wantHash: hasher.HashConfigMap(
&corev1.ConfigMap{
Data: map[string]string{
"key1": "value1",
"key2": "value2",
},
},
),
},
{
name: "configmap with binary data",
cm: &corev1.ConfigMap{
BinaryData: map[string][]byte{
"binary1": []byte("binaryvalue1"),
},
},
wantHash: hasher.HashConfigMap(
&corev1.ConfigMap{
BinaryData: map[string][]byte{
"binary1": []byte("binaryvalue1"),
},
},
),
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
got := hasher.HashConfigMap(tt.cm)
if got != tt.wantHash {
t.Errorf("HashConfigMap() = %v, want %v", got, tt.wantHash)
}
},
)
}
}
func TestHasher_HashConfigMap_Deterministic(t *testing.T) {
hasher := NewHasher()
cm := &corev1.ConfigMap{
Data: map[string]string{
"z-key": "value-z",
"a-key": "value-a",
"m-key": "value-m",
},
}
hash1 := hasher.HashConfigMap(cm)
hash2 := hasher.HashConfigMap(cm)
hash3 := hasher.HashConfigMap(cm)
if hash1 != hash2 || hash2 != hash3 {
t.Errorf("Hash is not deterministic: %s, %s, %s", hash1, hash2, hash3)
}
}
func TestHasher_HashConfigMap_DifferentValues(t *testing.T) {
hasher := NewHasher()
cm1 := &corev1.ConfigMap{
Data: map[string]string{
"key": "value1",
},
}
cm2 := &corev1.ConfigMap{
Data: map[string]string{
"key": "value2",
},
}
hash1 := hasher.HashConfigMap(cm1)
hash2 := hasher.HashConfigMap(cm2)
if hash1 == hash2 {
t.Errorf("Different values should produce different hashes")
}
}
func TestHasher_HashSecret(t *testing.T) {
hasher := NewHasher()
tests := []struct {
name string
secret *corev1.Secret
wantHash string
}{
{
name: "empty secret",
secret: &corev1.Secret{
Data: nil,
},
wantHash: hasher.HashSecret(&corev1.Secret{}),
},
{
name: "secret with data",
secret: &corev1.Secret{
Data: map[string][]byte{
"key1": []byte("value1"),
"key2": []byte("value2"),
},
},
wantHash: hasher.HashSecret(
&corev1.Secret{
Data: map[string][]byte{
"key1": []byte("value1"),
"key2": []byte("value2"),
},
},
),
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
got := hasher.HashSecret(tt.secret)
if got != tt.wantHash {
t.Errorf("HashSecret() = %v, want %v", got, tt.wantHash)
}
},
)
}
}
func TestHasher_HashSecret_Deterministic(t *testing.T) {
hasher := NewHasher()
secret := &corev1.Secret{
Data: map[string][]byte{
"z-key": []byte("value-z"),
"a-key": []byte("value-a"),
"m-key": []byte("value-m"),
},
}
hash1 := hasher.HashSecret(secret)
hash2 := hasher.HashSecret(secret)
hash3 := hasher.HashSecret(secret)
if hash1 != hash2 || hash2 != hash3 {
t.Errorf("Hash is not deterministic: %s, %s, %s", hash1, hash2, hash3)
}
}
func TestHasher_HashSecret_DifferentValues(t *testing.T) {
hasher := NewHasher()
secret1 := &corev1.Secret{
Data: map[string][]byte{
"key": []byte("value1"),
},
}
secret2 := &corev1.Secret{
Data: map[string][]byte{
"key": []byte("value2"),
},
}
hash1 := hasher.HashSecret(secret1)
hash2 := hasher.HashSecret(secret2)
if hash1 == hash2 {
t.Errorf("Different values should produce different hashes")
}
}
func TestHasher_EmptyHash(t *testing.T) {
hasher := NewHasher()
emptyHash := hasher.EmptyHash()
if emptyHash != "" {
t.Errorf("EmptyHash should be empty string, got %s", emptyHash)
}
cm := &corev1.ConfigMap{}
cmHash := hasher.HashConfigMap(cm)
if cmHash == "" {
t.Error("Empty ConfigMap should have a non-empty hash")
}
secret := &corev1.Secret{}
secretHash := hasher.HashSecret(secret)
if secretHash == "" {
t.Error("Empty Secret should have a non-empty hash")
}
}
func TestHasher_NilInput(t *testing.T) {
hasher := NewHasher()
cmHash := hasher.HashConfigMap(nil)
if cmHash == "" {
t.Error("nil ConfigMap should return a valid hash")
}
secretHash := hasher.HashSecret(nil)
if secretHash == "" {
t.Error("nil Secret should return a valid hash")
}
}
func TestHashSecretProviderClass(t *testing.T) {
h := NewHasher()
status := csiv1.SecretProviderClassPodStatusStatus{
SecretProviderClassName: "my-spc",
Objects: []csiv1.SecretProviderClassObject{
{ID: "secret/data/b", Version: "2"},
{ID: "secret/data/a", Version: "1"},
},
}
// Expected = SHA1 hex of the sorted, ';'-joined string, matching master.
expectedInput := "SecretProviderClassName=my-spc;secret/data/a=1;secret/data/b=2"
expected := h.computeSHA(expectedInput)
got := h.HashSecretProviderClass(status)
if got != expected {
t.Fatalf("HashSecretProviderClass = %q, want %q", got, expected)
}
// Order independence: shuffling objects must not change the hash.
statusReordered := csiv1.SecretProviderClassPodStatusStatus{
SecretProviderClassName: "my-spc",
Objects: []csiv1.SecretProviderClassObject{
{ID: "secret/data/a", Version: "1"},
{ID: "secret/data/b", Version: "2"},
},
}
if h.HashSecretProviderClass(statusReordered) != got {
t.Fatalf("hash not order-independent")
}
}
func TestHashSecretProviderClassEmpty(t *testing.T) {
h := NewHasher()
status := csiv1.SecretProviderClassPodStatusStatus{SecretProviderClassName: "empty"}
got := h.HashSecretProviderClass(status)
want := h.computeSHA("SecretProviderClassName=empty")
if got != want {
t.Fatalf("HashSecretProviderClass(empty) = %q, want %q", got, want)
}
}