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: "es.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") }