hash-of-wisdom/internal/protocol/spec_compliance_test.go

178 lines
5.2 KiB
Go

package protocol
import (
"bytes"
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"hash-of-wisdom/internal/pow/challenge"
"hash-of-wisdom/internal/quotes"
)
// TestSpecCompliance_ChallengeResponse verifies challenge response matches PROTOCOL.md format
func TestSpecCompliance_ChallengeResponse(t *testing.T) {
resp := &ChallengeResponse{
Challenge: &challenge.Challenge{
Timestamp: 1640995200,
Difficulty: 4,
Resource: "quotes",
Random: []byte{0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6},
HMAC: []byte("base64url_encoded_signature"),
},
}
var buf bytes.Buffer
err := resp.Encode(&buf)
require.NoError(t, err)
// Skip header (5 bytes) and get payload
header := buf.Bytes()[:5]
payload := buf.Bytes()[5:]
// Verify header format
assert.Equal(t, byte(ChallengeResponseType), header[0])
assert.Equal(t, uint32(len(payload)), uint32(header[1])<<24|uint32(header[2])<<16|uint32(header[3])<<8|uint32(header[4]))
// Verify JSON payload matches spec format
var decoded map[string]interface{}
err = json.Unmarshal(payload, &decoded)
require.NoError(t, err)
// Check required fields from spec
assert.Contains(t, decoded, "timestamp")
assert.Contains(t, decoded, "difficulty")
assert.Contains(t, decoded, "resource")
assert.Contains(t, decoded, "random")
assert.Contains(t, decoded, "hmac")
assert.Equal(t, float64(1640995200), decoded["timestamp"])
assert.Equal(t, float64(4), decoded["difficulty"])
assert.Equal(t, "quotes", decoded["resource"])
}
// TestSpecCompliance_SolutionRequest verifies solution request matches PROTOCOL.md format
func TestSpecCompliance_SolutionRequest(t *testing.T) {
req := &SolutionRequest{
Challenge: challenge.Challenge{
Timestamp: 1640995200,
Difficulty: 4,
Resource: "quotes",
Random: []byte{0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6},
HMAC: []byte("base64url_encoded_signature"),
},
Nonce: 12345,
}
var buf bytes.Buffer
err := req.Encode(&buf)
require.NoError(t, err)
// Skip header and get payload
payload := buf.Bytes()[5:]
// Verify JSON payload matches spec format
var decoded map[string]interface{}
err = json.Unmarshal(payload, &decoded)
require.NoError(t, err)
// Check required top-level fields
assert.Contains(t, decoded, "challenge")
assert.Contains(t, decoded, "nonce")
assert.Equal(t, float64(12345), decoded["nonce"])
// Check challenge structure
challenge := decoded["challenge"].(map[string]interface{})
assert.Contains(t, challenge, "timestamp")
assert.Contains(t, challenge, "difficulty")
assert.Contains(t, challenge, "resource")
assert.Contains(t, challenge, "random")
assert.Contains(t, challenge, "hmac")
}
// TestSpecCompliance_QuoteResponse verifies quote response matches PROTOCOL.md format
func TestSpecCompliance_QuoteResponse(t *testing.T) {
resp := &SolutionResponse{
Quote: &quotes.Quote{
Text: "The only way to do great work is to love what you do.",
Author: "Steve Jobs",
},
}
var buf bytes.Buffer
err := resp.Encode(&buf)
require.NoError(t, err)
// Skip header and get payload
payload := buf.Bytes()[5:]
// Verify JSON payload matches spec format
var decoded map[string]interface{}
err = json.Unmarshal(payload, &decoded)
require.NoError(t, err)
// Check required fields from spec
assert.Contains(t, decoded, "text")
assert.Contains(t, decoded, "author")
assert.Equal(t, "The only way to do great work is to love what you do.", decoded["text"])
assert.Equal(t, "Steve Jobs", decoded["author"])
}
// TestSpecCompliance_ErrorResponse verifies error response matches PROTOCOL.md format
func TestSpecCompliance_ErrorResponse(t *testing.T) {
resp := &ErrorResponse{
Code: "INVALID_SOLUTION",
Message: "The provided PoW solution is incorrect",
RetryAfter: 30,
Details: map[string]string{"reason": "hash verification failed"},
}
var buf bytes.Buffer
err := resp.Encode(&buf)
require.NoError(t, err)
// Skip header and get payload
payload := buf.Bytes()[5:]
// Verify JSON payload matches spec format
var decoded map[string]interface{}
err = json.Unmarshal(payload, &decoded)
require.NoError(t, err)
// Check required fields from spec
assert.Contains(t, decoded, "code")
assert.Contains(t, decoded, "message")
assert.Equal(t, "INVALID_SOLUTION", decoded["code"])
assert.Equal(t, "The provided PoW solution is incorrect", decoded["message"])
// Check optional fields
assert.Contains(t, decoded, "retry_after")
assert.Contains(t, decoded, "details")
assert.Equal(t, float64(30), decoded["retry_after"])
}
// TestSpecCompliance_MessageSizeLimits verifies 8KB payload limit
func TestSpecCompliance_MessageSizeLimits(t *testing.T) {
decoder := NewMessageDecoder()
// Create a message that exceeds 8KB payload limit
largePayload := make([]byte, MaxPayloadSize+1)
for i := range largePayload {
largePayload[i] = 'A'
}
// Create message with oversized payload
var buf bytes.Buffer
buf.WriteByte(byte(ChallengeRequestType))
buf.Write([]byte{0x00, 0x00, 0x20, 0x01}) // 8193 bytes (8KB + 1)
buf.Write(largePayload)
// Should reject oversized payload
_, err := decoder.Decode(&buf)
assert.Error(t, err)
assert.Contains(t, err.Error(), "payload length")
assert.Contains(t, err.Error(), "exceeds maximum")
}