Files
realy/sha256/additional_test.go
mleku 5bf9d72518 Add comprehensive tests for sha256 marshalling and unmarshalling
Introduce tests to verify `MarshalBinary` and `UnmarshalBinary` behavior, covering block boundary cases, data integrity after state restoration, and error handling for invalid inputs. These tests ensure correctness for diverse data sizes, edge cases, and error scenarios.
2025-06-26 21:28:52 +01:00

198 lines
4.9 KiB
Go

package sha256
import (
"bytes"
"fmt"
"testing"
)
// Test for the UnmarshalBinary issue where d.nx calculation might be incorrect
func TestUnmarshalBinaryNxCalculation(t *testing.T) {
// Create a digest and write some data that doesn't align to block boundary
d1 := New().(*digest)
testData := []byte("hello world") // 11 bytes, not aligned to 64-byte boundary
d1.Write(testData)
// Marshal the state
state, err := d1.MarshalBinary()
if err != nil {
t.Fatalf("MarshalBinary failed: %v", err)
}
// Create a new digest and unmarshal
d2 := New().(*digest)
err = d2.UnmarshalBinary(state)
if err != nil {
t.Fatalf("UnmarshalBinary failed: %v", err)
}
// Check that nx values match
if d1.nx != d2.nx {
t.Errorf("nx mismatch after unmarshal: original=%d, unmarshaled=%d", d1.nx, d2.nx)
}
// Check that the buffer contents match
if !bytes.Equal(d1.x[:d1.nx], d2.x[:d2.nx]) {
t.Errorf("buffer contents mismatch after unmarshal")
}
// Continue writing and verify results match
moreData := []byte(" more data")
d1.Write(moreData)
d2.Write(moreData)
sum1 := d1.Sum(nil)
sum2 := d2.Sum(nil)
if !bytes.Equal(sum1, sum2) {
t.Errorf("final sums don't match: %x vs %x", sum1, sum2)
}
}
// Test edge case with exactly block-sized data
func TestUnmarshalBinaryBlockBoundary(t *testing.T) {
// Create data that's exactly one block (64 bytes)
testData := make([]byte, BlockSize)
for i := range testData {
testData[i] = byte(i)
}
d1 := New().(*digest)
d1.Write(testData)
// Marshal and unmarshal
state, err := d1.MarshalBinary()
if err != nil {
t.Fatalf("MarshalBinary failed: %v", err)
}
d2 := New().(*digest)
err = d2.UnmarshalBinary(state)
if err != nil {
t.Fatalf("UnmarshalBinary failed: %v", err)
}
// After writing exactly one block, nx should be 0
if d1.nx != 0 || d2.nx != 0 {
t.Errorf("nx should be 0 after block boundary: d1.nx=%d, d2.nx=%d", d1.nx, d2.nx)
}
// Verify final results match
sum1 := d1.Sum(nil)
sum2 := d2.Sum(nil)
if !bytes.Equal(sum1, sum2) {
t.Errorf("final sums don't match: %x vs %x", sum1, sum2)
}
}
// Test marshaling/unmarshaling with various data sizes
func TestMarshalUnmarshalVariousSizes(t *testing.T) {
sizes := []int{0, 1, 32, 63, 64, 65, 127, 128, 129}
for _, size := range sizes {
t.Run(fmt.Sprintf("size_%d", size), func(t *testing.T) {
testData := make([]byte, size)
for i := range testData {
testData[i] = byte(i % 256)
}
d1 := New().(*digest)
d1.Write(testData)
// Marshal
state, err := d1.MarshalBinary()
if err != nil {
t.Fatalf("MarshalBinary failed for size %d: %v", size, err)
}
// Unmarshal
d2 := New().(*digest)
err = d2.UnmarshalBinary(state)
if err != nil {
t.Fatalf("UnmarshalBinary failed for size %d: %v", size, err)
}
// Verify state matches
if d1.nx != d2.nx {
t.Errorf("nx mismatch for size %d: %d vs %d", size, d1.nx, d2.nx)
}
if d1.len != d2.len {
t.Errorf("len mismatch for size %d: %d vs %d", size, d1.len, d2.len)
}
// Verify final results match
sum1 := d1.Sum(nil)
sum2 := d2.Sum(nil)
if !bytes.Equal(sum1, sum2) {
t.Errorf("final sums don't match for size %d: %x vs %x", size, sum1, sum2)
}
})
}
}
// Test the getDigest function to ensure it correctly extracts digest values
func TestGetDigest(t *testing.T) {
// Create a test state array with known values
state := make([]byte, 512)
// Fill with a pattern that we can verify
for i := 0; i < 512; i++ {
state[i] = byte(i % 256)
}
// Test extracting digest for different indices
for index := 0; index < 16; index++ {
digest := getDigest(index, state)
// Verify the digest has the expected size
if len(digest) != Size {
t.Errorf("digest size mismatch for index %d: got %d, want %d", index, len(digest), Size)
}
// The digest should not be all zeros (unless the state was all zeros)
allZero := true
for _, b := range digest {
if b != 0 {
allZero = false
break
}
}
// Since we filled state with a pattern, digest shouldn't be all zeros
if allZero {
t.Errorf("digest for index %d is all zeros, which is unexpected", index)
}
}
}
// Test error handling in UnmarshalBinary
func TestUnmarshalBinaryErrorHandling(t *testing.T) {
d := New().(*digest)
// Test with invalid magic
invalidMagic := []byte("bad\x03" + string(make([]byte, marshaledSize-4)))
err := d.UnmarshalBinary(invalidMagic)
if err == nil {
t.Error("expected error for invalid magic, got nil")
}
// Test with invalid size
validMagic := []byte("sha\x03")
tooShort := append(validMagic, make([]byte, 10)...)
err = d.UnmarshalBinary(tooShort)
if err == nil {
t.Error("expected error for invalid size, got nil")
}
// Test with exactly the minimum size but wrong magic
exactSize := make([]byte, marshaledSize)
copy(exactSize, "bad\x03")
err = d.UnmarshalBinary(exactSize)
if err == nil {
t.Error("expected error for wrong magic with correct size, got nil")
}
}