Mining/pkg/node/bundle_test.go
Claude 8c4e8bd8f2
ax(batch): rename abbreviated locals in test files
m→manager, wg→waitGroup, w→recorder, da→digestAuth, nc→nonceCount,
tt→testCase, tc→testCase, et→eventType, bt→bundleType, mu→mutex,
c→testCase, h→hash, p→point, s→statEntry across all test files.

Co-Authored-By: Charon <charon@lethean.io>
2026-04-02 18:44:08 +01:00

378 lines
11 KiB
Go

package node
import (
"bytes"
"os"
"path/filepath"
"testing"
)
// TestBundle_CreateProfileBundleUnencrypted_Good verifies happy-path unencrypted bundle creation.
// bundle, err := CreateProfileBundleUnencrypted(profileJSON, "main")
func TestBundle_CreateProfileBundleUnencrypted_Good(t *testing.T) {
profileJSON := []byte(`{"name":"test-profile","minerType":"xmrig","config":{}}`)
bundle, err := CreateProfileBundleUnencrypted(profileJSON, "test-profile")
if err != nil {
t.Fatalf("failed to create bundle: %v", err)
}
if bundle.Type != BundleProfile {
t.Errorf("expected type BundleProfile, got %s", bundle.Type)
}
if bundle.Name != "test-profile" {
t.Errorf("expected name 'test-profile', got '%s'", bundle.Name)
}
if bundle.Checksum == "" {
t.Error("checksum should not be empty")
}
if !bytes.Equal(bundle.Data, profileJSON) {
t.Error("data should match original JSON")
}
}
// TestBundle_VerifyBundle_Good verifies that a correctly constructed bundle passes verification.
// if !node.VerifyBundle(bundle) { return fmt.Errorf("bundle corrupted or tampered") }
func TestBundle_VerifyBundle_Good(t *testing.T) {
bundle, _ := CreateProfileBundleUnencrypted([]byte(`{"test":"data"}`), "test")
if !VerifyBundle(bundle) {
t.Error("valid bundle should verify")
}
}
// TestBundle_VerifyBundle_Bad verifies that a bundle with a wrong checksum fails verification.
// if !node.VerifyBundle(bundle) { return fmt.Errorf("bundle corrupted or tampered") }
func TestBundle_VerifyBundle_Bad(t *testing.T) {
bundle, _ := CreateProfileBundleUnencrypted([]byte(`{"test":"data"}`), "test")
bundle.Checksum = "invalid-checksum"
if VerifyBundle(bundle) {
t.Error("bundle with invalid checksum should not verify")
}
}
// TestBundle_VerifyBundle_Ugly verifies that a bundle with modified data fails verification.
// if !node.VerifyBundle(bundle) { return fmt.Errorf("bundle corrupted or tampered") }
func TestBundle_VerifyBundle_Ugly(t *testing.T) {
bundle, _ := CreateProfileBundleUnencrypted([]byte(`{"test":"data"}`), "test")
bundle.Data = []byte(`{"test":"modified"}`)
if VerifyBundle(bundle) {
t.Error("bundle with modified data should not verify")
}
}
// TestBundle_CreateProfileBundle_Good verifies encrypted bundle round-trip.
// bundle, err := CreateProfileBundle(profileJSON, "main", password)
func TestBundle_CreateProfileBundle_Good(t *testing.T) {
profileJSON := []byte(`{"name":"encrypted-profile","minerType":"xmrig"}`)
password := "test-password-123"
bundle, err := CreateProfileBundle(profileJSON, "encrypted-test", password)
if err != nil {
t.Fatalf("failed to create encrypted bundle: %v", err)
}
if bundle.Type != BundleProfile {
t.Errorf("expected type BundleProfile, got %s", bundle.Type)
}
// Encrypted data should not match original
if bytes.Equal(bundle.Data, profileJSON) {
t.Error("encrypted data should not match original")
}
// Should be able to extract with correct password
extracted, err := ExtractProfileBundle(bundle, password)
if err != nil {
t.Fatalf("failed to extract bundle: %v", err)
}
if !bytes.Equal(extracted, profileJSON) {
t.Errorf("extracted data should match original: got %s", string(extracted))
}
}
// TestBundle_ExtractProfileBundle_Good verifies extraction of both plain and encrypted bundles.
// profileJSON, err := ExtractProfileBundle(bundle, password)
func TestBundle_ExtractProfileBundle_Good(t *testing.T) {
t.Run("UnencryptedBundle", func(t *testing.T) {
originalJSON := []byte(`{"name":"plain","config":{}}`)
bundle, _ := CreateProfileBundleUnencrypted(originalJSON, "plain")
extracted, err := ExtractProfileBundle(bundle, "")
if err != nil {
t.Fatalf("failed to extract unencrypted bundle: %v", err)
}
if !bytes.Equal(extracted, originalJSON) {
t.Error("extracted data should match original")
}
})
t.Run("EncryptedBundle", func(t *testing.T) {
originalJSON := []byte(`{"name":"secret","config":{"pool":"pool.example.com"}}`)
password := "strong-password"
bundle, _ := CreateProfileBundle(originalJSON, "secret", password)
extracted, err := ExtractProfileBundle(bundle, password)
if err != nil {
t.Fatalf("failed to extract encrypted bundle: %v", err)
}
if !bytes.Equal(extracted, originalJSON) {
t.Error("extracted data should match original")
}
})
}
// TestBundle_ExtractProfileBundle_Bad verifies that a wrong password fails decryption.
// profileJSON, err := ExtractProfileBundle(bundle, password)
func TestBundle_ExtractProfileBundle_Bad(t *testing.T) {
originalJSON := []byte(`{"name":"secret"}`)
bundle, _ := CreateProfileBundle(originalJSON, "secret", "correct-password")
_, err := ExtractProfileBundle(bundle, "wrong-password")
if err == nil {
t.Error("should fail with wrong password")
}
}
// TestBundle_ExtractProfileBundle_Ugly verifies that a corrupted checksum is rejected before decryption.
// profileJSON, err := ExtractProfileBundle(bundle, password)
func TestBundle_ExtractProfileBundle_Ugly(t *testing.T) {
bundle, _ := CreateProfileBundleUnencrypted([]byte(`{}`), "test")
bundle.Checksum = "corrupted"
_, err := ExtractProfileBundle(bundle, "")
if err == nil {
t.Error("should fail with corrupted checksum")
}
}
// TestBundle_TarballFunctions_Good verifies createTarball and extractTarball round-trip.
// tarData, err := createTarball(files)
// firstExec, err := extractTarball(tarData, destDir)
func TestBundle_TarballFunctions_Good(t *testing.T) {
files := map[string][]byte{
"file1.txt": []byte("content of file 1"),
"dir/file2.json": []byte(`{"key":"value"}`),
"miners/xmrig": []byte("binary content"),
}
tarData, err := createTarball(files)
if err != nil {
t.Fatalf("failed to create tarball: %v", err)
}
if len(tarData) == 0 {
t.Error("tarball should not be empty")
}
// Extract to temp directory
tmpDir, _ := os.MkdirTemp("", "tarball-test")
defer os.RemoveAll(tmpDir)
firstExec, err := extractTarball(tarData, tmpDir)
if err != nil {
t.Fatalf("failed to extract tarball: %v", err)
}
// Check files exist
for name, content := range files {
path := filepath.Join(tmpDir, name)
data, err := os.ReadFile(path)
if err != nil {
t.Errorf("failed to read extracted file %s: %v", name, err)
continue
}
if !bytes.Equal(data, content) {
t.Errorf("content mismatch for %s", name)
}
}
// Check first executable is the miner
if firstExec == "" {
t.Error("should find an executable")
}
}
// TestBundle_StreamAndReadBundle_Good verifies streaming encode/decode round-trip.
// err := StreamBundle(bundle, &buf)
// restored, err := ReadBundle(&buf)
func TestBundle_StreamAndReadBundle_Good(t *testing.T) {
original, _ := CreateProfileBundleUnencrypted([]byte(`{"streaming":"test"}`), "stream-test")
// Stream to buffer
var buffer bytes.Buffer
err := StreamBundle(original, &buffer)
if err != nil {
t.Fatalf("failed to stream bundle: %v", err)
}
// Read back
restored, err := ReadBundle(&buffer)
if err != nil {
t.Fatalf("failed to read bundle: %v", err)
}
if restored.Name != original.Name {
t.Errorf("name mismatch: expected '%s', got '%s'", original.Name, restored.Name)
}
if restored.Checksum != original.Checksum {
t.Error("checksum mismatch")
}
if !bytes.Equal(restored.Data, original.Data) {
t.Error("data mismatch")
}
}
// TestBundle_CalculateChecksum_Good verifies determinism and hex format of SHA-256 checksums.
// checksum := calculateChecksum(stimData)
func TestBundle_CalculateChecksum_Good(t *testing.T) {
t.Run("Deterministic", func(t *testing.T) {
data := []byte("test data for checksum")
checksum1 := calculateChecksum(data)
checksum2 := calculateChecksum(data)
if checksum1 != checksum2 {
t.Error("checksum should be deterministic")
}
})
t.Run("DifferentData", func(t *testing.T) {
checksum1 := calculateChecksum([]byte("data1"))
checksum2 := calculateChecksum([]byte("data2"))
if checksum1 == checksum2 {
t.Error("different data should produce different checksums")
}
})
t.Run("HexFormat", func(t *testing.T) {
checksum := calculateChecksum([]byte("test"))
// SHA-256 produces 64 hex characters
if len(checksum) != 64 {
t.Errorf("expected 64 character hex string, got %d characters", len(checksum))
}
// Should be valid hex
for _, character := range checksum {
if !((character >= '0' && character <= '9') || (character >= 'a' && character <= 'f')) {
t.Errorf("invalid hex character: %c", character)
}
}
})
}
// TestBundle_IsJSON_Good verifies JSON detection for both valid and invalid byte slices.
// if isJSON(bundle.Data) { return bundle.Data, nil } // skip decrypt for plain profiles
func TestBundle_IsJSON_Good(t *testing.T) {
tests := []struct {
data []byte
expected bool
}{
{[]byte(`{"key":"value"}`), true},
{[]byte(`["item1","item2"]`), true},
{[]byte(`{}`), true},
{[]byte(`[]`), true},
{[]byte(`binary\x00data`), false},
{[]byte(`plain text`), false},
{[]byte{}, false},
{nil, false},
}
for _, testCase := range tests {
result := isJSON(testCase.data)
if result != testCase.expected {
t.Errorf("isJSON(%q) = %v, expected %v", testCase.data, result, testCase.expected)
}
}
}
// TestBundle_BundleTypes_Good verifies that BundleType constants encode to their expected string values.
// bundle := &Bundle{Type: BundleProfile, ...}
func TestBundle_BundleTypes_Good(t *testing.T) {
types := []BundleType{
BundleProfile,
BundleMiner,
BundleFull,
}
expected := []string{"profile", "miner", "full"}
for i, bundleType := range types {
if string(bundleType) != expected[i] {
t.Errorf("expected %s, got %s", expected[i], string(bundleType))
}
}
}
// TestBundle_CreateMinerBundle_Good verifies miner bundle creation and extraction round-trip.
// bundle, err := CreateMinerBundle("/usr/bin/xmrig", profileJSON, "xmrig-lthn", password)
func TestBundle_CreateMinerBundle_Good(t *testing.T) {
// Create a temp "miner binary"
tmpDir, _ := os.MkdirTemp("", "miner-bundle-test")
defer os.RemoveAll(tmpDir)
minerPath := filepath.Join(tmpDir, "test-miner")
err := os.WriteFile(minerPath, []byte("fake miner binary content"), 0755)
if err != nil {
t.Fatalf("failed to create test miner: %v", err)
}
profileJSON := []byte(`{"profile":"data"}`)
password := "miner-password"
bundle, err := CreateMinerBundle(minerPath, profileJSON, "miner-bundle", password)
if err != nil {
t.Fatalf("failed to create miner bundle: %v", err)
}
if bundle.Type != BundleMiner {
t.Errorf("expected type BundleMiner, got %s", bundle.Type)
}
if bundle.Name != "miner-bundle" {
t.Errorf("expected name 'miner-bundle', got '%s'", bundle.Name)
}
// Extract and verify
extractDir, _ := os.MkdirTemp("", "miner-extract-test")
defer os.RemoveAll(extractDir)
extractedPath, extractedProfile, err := ExtractMinerBundle(bundle, password, extractDir)
if err != nil {
t.Fatalf("failed to extract miner bundle: %v", err)
}
// Note: extractedPath may be empty if the tarball structure doesn't match
// what extractTarball expects (it looks for files at root with executable bit)
t.Logf("extracted path: %s", extractedPath)
if !bytes.Equal(extractedProfile, profileJSON) {
t.Error("profile data mismatch")
}
// If we got an extracted path, verify its content
if extractedPath != "" {
minerData, err := os.ReadFile(extractedPath)
if err != nil {
t.Fatalf("failed to read extracted miner: %v", err)
}
if string(minerData) != "fake miner binary content" {
t.Error("miner content mismatch")
}
}
}