cli/pkg/crypt/crypt_test.go

366 lines
9.4 KiB
Go

package crypt
import (
"bytes"
"testing"
"github.com/Snider/Core/pkg/core"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// --- Constructor Tests ---
func TestNew(t *testing.T) {
t.Run("creates service successfully", func(t *testing.T) {
service, err := New()
assert.NoError(t, err)
assert.NotNil(t, service)
})
t.Run("returns independent instances", func(t *testing.T) {
service1, err1 := New()
service2, err2 := New()
assert.NoError(t, err1)
assert.NoError(t, err2)
assert.NotSame(t, service1, service2)
})
}
func TestRegister(t *testing.T) {
t.Run("registers with core successfully", func(t *testing.T) {
coreInstance, err := core.New()
require.NoError(t, err)
service, err := Register(coreInstance)
require.NoError(t, err)
assert.NotNil(t, service)
})
t.Run("returns Service type with Runtime", func(t *testing.T) {
coreInstance, err := core.New()
require.NoError(t, err)
service, err := Register(coreInstance)
require.NoError(t, err)
cryptService, ok := service.(*Service)
assert.True(t, ok)
assert.NotNil(t, cryptService.Runtime)
})
}
// --- Hash Tests ---
func TestHash(t *testing.T) {
s, _ := New()
t.Run("LTHN hash", func(t *testing.T) {
hash := s.Hash(LTHN, "hello")
assert.NotEmpty(t, hash)
// LTHN hash should be consistent
hash2 := s.Hash(LTHN, "hello")
assert.Equal(t, hash, hash2)
})
t.Run("SHA512 hash", func(t *testing.T) {
hash := s.Hash(SHA512, "hello")
// Known SHA512 hash for "hello"
expected := "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043"
assert.Equal(t, expected, hash)
})
t.Run("SHA256 hash", func(t *testing.T) {
hash := s.Hash(SHA256, "hello")
// Known SHA256 hash for "hello"
expected := "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
assert.Equal(t, expected, hash)
})
t.Run("SHA1 hash", func(t *testing.T) {
hash := s.Hash(SHA1, "hello")
// Known SHA1 hash for "hello"
expected := "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d"
assert.Equal(t, expected, hash)
})
t.Run("MD5 hash", func(t *testing.T) {
hash := s.Hash(MD5, "hello")
// Known MD5 hash for "hello"
expected := "5d41402abc4b2a76b9719d911017c592"
assert.Equal(t, expected, hash)
})
t.Run("default falls back to SHA256", func(t *testing.T) {
hash := s.Hash("unknown", "hello")
sha256Hash := s.Hash(SHA256, "hello")
assert.Equal(t, sha256Hash, hash)
})
t.Run("empty string hash", func(t *testing.T) {
hash := s.Hash(SHA256, "")
// Known SHA256 hash for empty string
expected := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
assert.Equal(t, expected, hash)
})
t.Run("hash with special characters", func(t *testing.T) {
hash := s.Hash(SHA256, "hello!@#$%^&*()")
assert.NotEmpty(t, hash)
assert.Len(t, hash, 64) // SHA256 produces 64 hex chars
})
t.Run("hash with unicode", func(t *testing.T) {
hash := s.Hash(SHA256, "你好世界")
assert.NotEmpty(t, hash)
assert.Len(t, hash, 64)
})
t.Run("hash consistency", func(t *testing.T) {
payload := "test payload for consistency check"
for _, hashType := range []HashType{LTHN, SHA512, SHA256, SHA1, MD5} {
hash1 := s.Hash(hashType, payload)
hash2 := s.Hash(hashType, payload)
assert.Equal(t, hash1, hash2, "Hash should be consistent for %s", hashType)
}
})
}
// --- Luhn Tests ---
func TestLuhn(t *testing.T) {
s, _ := New()
t.Run("valid Luhn numbers", func(t *testing.T) {
validNumbers := []string{
"79927398713",
"4532015112830366", // Visa test number
"6011514433546201", // Discover test number
"371449635398431", // Amex test number
"30569309025904", // Diners Club test number
}
for _, num := range validNumbers {
assert.True(t, s.Luhn(num), "Expected %s to be valid", num)
}
})
t.Run("invalid Luhn numbers", func(t *testing.T) {
invalidNumbers := []string{
"79927398714",
"1234567890",
"1111111111",
"1234567891",
}
for _, num := range invalidNumbers {
assert.False(t, s.Luhn(num), "Expected %s to be invalid", num)
}
})
t.Run("all zeros is valid", func(t *testing.T) {
// All zeros: each digit contributes 0, sum=0, 0%10==0
assert.True(t, s.Luhn("0000000000"))
})
t.Run("handles spaces", func(t *testing.T) {
// Same number with and without spaces should give same result
assert.True(t, s.Luhn("7992 7398 713"))
assert.True(t, s.Luhn("4532 0151 1283 0366"))
})
t.Run("non-digit characters return false", func(t *testing.T) {
assert.False(t, s.Luhn("1234abcd5678"))
assert.False(t, s.Luhn("12-34-56-78"))
assert.False(t, s.Luhn("1234.5678"))
})
t.Run("empty string", func(t *testing.T) {
// Empty string: sum=0, 0%10==0, so it returns true
assert.True(t, s.Luhn(""))
})
t.Run("single digit", func(t *testing.T) {
assert.True(t, s.Luhn("0"))
assert.False(t, s.Luhn("1"))
})
}
// --- Fletcher Checksum Tests ---
func TestFletcher16(t *testing.T) {
s, _ := New()
t.Run("basic checksum", func(t *testing.T) {
checksum := s.Fletcher16("hello")
assert.NotZero(t, checksum)
})
t.Run("empty string", func(t *testing.T) {
checksum := s.Fletcher16("")
assert.Equal(t, uint16(0), checksum)
})
t.Run("consistency", func(t *testing.T) {
checksum1 := s.Fletcher16("test data")
checksum2 := s.Fletcher16("test data")
assert.Equal(t, checksum1, checksum2)
})
t.Run("different inputs produce different checksums", func(t *testing.T) {
checksum1 := s.Fletcher16("hello")
checksum2 := s.Fletcher16("world")
assert.NotEqual(t, checksum1, checksum2)
})
t.Run("known value", func(t *testing.T) {
// "abcde" has a known Fletcher-16 checksum
checksum := s.Fletcher16("abcde")
assert.NotZero(t, checksum)
})
}
func TestFletcher32(t *testing.T) {
s, _ := New()
t.Run("basic checksum", func(t *testing.T) {
checksum := s.Fletcher32("hello")
assert.NotZero(t, checksum)
})
t.Run("empty string", func(t *testing.T) {
checksum := s.Fletcher32("")
assert.Equal(t, uint32(0), checksum)
})
t.Run("consistency", func(t *testing.T) {
checksum1 := s.Fletcher32("test data")
checksum2 := s.Fletcher32("test data")
assert.Equal(t, checksum1, checksum2)
})
t.Run("different inputs produce different checksums", func(t *testing.T) {
checksum1 := s.Fletcher32("hello")
checksum2 := s.Fletcher32("world")
assert.NotEqual(t, checksum1, checksum2)
})
t.Run("handles odd-length input", func(t *testing.T) {
// Odd length input should be padded
checksum := s.Fletcher32("abc")
assert.NotZero(t, checksum)
})
t.Run("handles even-length input", func(t *testing.T) {
checksum := s.Fletcher32("abcd")
assert.NotZero(t, checksum)
})
}
func TestFletcher64(t *testing.T) {
s, _ := New()
t.Run("basic checksum", func(t *testing.T) {
checksum := s.Fletcher64("hello")
assert.NotZero(t, checksum)
})
t.Run("empty string", func(t *testing.T) {
checksum := s.Fletcher64("")
assert.Equal(t, uint64(0), checksum)
})
t.Run("consistency", func(t *testing.T) {
checksum1 := s.Fletcher64("test data")
checksum2 := s.Fletcher64("test data")
assert.Equal(t, checksum1, checksum2)
})
t.Run("different inputs produce different checksums", func(t *testing.T) {
checksum1 := s.Fletcher64("hello")
checksum2 := s.Fletcher64("world")
assert.NotEqual(t, checksum1, checksum2)
})
t.Run("handles various input lengths", func(t *testing.T) {
// Test padding for different lengths
for i := 1; i <= 8; i++ {
input := string(make([]byte, i))
checksum := s.Fletcher64(input)
// Just verify it doesn't panic
_ = checksum
}
})
t.Run("long input", func(t *testing.T) {
// Use actual text content, not null bytes
longInput := ""
for i := 0; i < 100; i++ {
longInput += "test data "
}
checksum := s.Fletcher64(longInput)
assert.NotZero(t, checksum)
})
}
// --- HashType Constants Tests ---
func TestHashTypeConstants(t *testing.T) {
t.Run("constants have expected values", func(t *testing.T) {
assert.Equal(t, HashType("lthn"), LTHN)
assert.Equal(t, HashType("sha512"), SHA512)
assert.Equal(t, HashType("sha256"), SHA256)
assert.Equal(t, HashType("sha1"), SHA1)
assert.Equal(t, HashType("md5"), MD5)
})
}
// --- PGP Tests (basic, detailed tests in openpgp package) ---
func TestEncryptPGP(t *testing.T) {
t.Run("requires valid key paths", func(t *testing.T) {
s, _ := New()
var buf bytes.Buffer
// Should fail with invalid path
_, err := s.EncryptPGP(&buf, "/nonexistent/path", "test data", nil, nil)
assert.Error(t, err)
})
}
func TestDecryptPGP(t *testing.T) {
t.Run("requires valid key paths", func(t *testing.T) {
s, _ := New()
// Should fail with invalid path
_, err := s.DecryptPGP("/nonexistent/path", "encrypted data", "passphrase", nil)
assert.Error(t, err)
})
}
// --- HandleIPCEvents Tests ---
func TestHandleIPCEvents(t *testing.T) {
t.Run("handles ActionServiceStartup", func(t *testing.T) {
coreInstance, err := core.New()
require.NoError(t, err)
serviceAny, err := Register(coreInstance)
require.NoError(t, err)
s := serviceAny.(*Service)
err = s.HandleIPCEvents(coreInstance, core.ActionServiceStartup{})
assert.NoError(t, err)
})
t.Run("handles unknown message type", func(t *testing.T) {
coreInstance, err := core.New()
require.NoError(t, err)
serviceAny, err := Register(coreInstance)
require.NoError(t, err)
s := serviceAny.(*Service)
// Pass an arbitrary type as unknown message
err = s.HandleIPCEvents(coreInstance, "unknown message")
assert.NoError(t, err)
})
}