| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- package dto
- import (
- "testing"
- "github.com/QuantumNous/new-api/common"
- "github.com/stretchr/testify/require"
- "github.com/tidwall/gjson"
- )
- // TestMessageReasoningContentPreservesEmptyString verifies that an explicitly
- // set empty reasoning_content string survives the JSON round-trip.
- //
- // This is critical for the request-forwarding path (non-passThrough mode):
- // the gateway unmarshals the client request into GeneralOpenAIRequest, then
- // re-marshals it before sending upstream. If Message.ReasoningContent were
- // `string` + `omitempty` (the old type), the empty string would be silently
- // dropped, causing the upstream to never receive the field.
- //
- // With the fix (`*string` + `omitempty`), nil = absent, &"" = explicit empty.
- func TestMessageReasoningContentPreservesEmptyString(t *testing.T) {
- raw := []byte(`{
- "role": "assistant",
- "content": "Hello",
- "reasoning_content": "",
- "reasoning": ""
- }`)
- var msg Message
- err := common.Unmarshal(raw, &msg)
- require.NoError(t, err)
- // Pointers must be non-nil: the field was explicitly set to ""
- require.NotNil(t, msg.ReasoningContent, "reasoning_content should be non-nil when explicitly set to empty string")
- require.NotNil(t, msg.Reasoning, "reasoning should be non-nil when explicitly set to empty string")
- require.Equal(t, "", *msg.ReasoningContent)
- require.Equal(t, "", *msg.Reasoning)
- // Re-marshal — the fields must still be present in the output JSON
- encoded, err := common.Marshal(msg)
- require.NoError(t, err)
- require.True(t, gjson.GetBytes(encoded, "reasoning_content").Exists(),
- "reasoning_content should exist in re-marshaled JSON when explicitly set to empty string")
- require.True(t, gjson.GetBytes(encoded, "reasoning").Exists(),
- "reasoning should exist in re-marshaled JSON when explicitly set to empty string")
- require.Equal(t, "", gjson.GetBytes(encoded, "reasoning_content").String())
- require.Equal(t, "", gjson.GetBytes(encoded, "reasoning").String())
- }
- // TestMessageReasoningContentOmitsAbsentField verifies that when
- // reasoning_content / reasoning are absent from the input JSON, they remain
- // absent after a round-trip (nil pointer → omitted by omitempty).
- func TestMessageReasoningContentOmitsAbsentField(t *testing.T) {
- raw := []byte(`{
- "role": "assistant",
- "content": "Hello"
- }`)
- var msg Message
- err := common.Unmarshal(raw, &msg)
- require.NoError(t, err)
- // Pointers must be nil: the fields were not present in the input
- require.Nil(t, msg.ReasoningContent)
- require.Nil(t, msg.Reasoning)
- // Re-marshal — the fields must NOT appear in the output JSON
- encoded, err := common.Marshal(msg)
- require.NoError(t, err)
- require.False(t, gjson.GetBytes(encoded, "reasoning_content").Exists(),
- "reasoning_content should not exist in re-marshaled JSON when absent from input")
- require.False(t, gjson.GetBytes(encoded, "reasoning").Exists(),
- "reasoning should not exist in re-marshaled JSON when absent from input")
- }
- // TestMessageGetReasoningContent verifies the GetReasoningContent helper
- // method that is used in token-counting code paths.
- func TestMessageGetReasoningContent(t *testing.T) {
- t.Run("both nil returns empty", func(t *testing.T) {
- msg := Message{Role: "assistant"}
- require.Equal(t, "", msg.GetReasoningContent())
- })
- t.Run("ReasoningContent takes priority", func(t *testing.T) {
- rc := "thinking..."
- r := "should be ignored"
- msg := Message{ReasoningContent: &rc, Reasoning: &r}
- require.Equal(t, "thinking...", msg.GetReasoningContent())
- })
- t.Run("falls back to Reasoning when ReasoningContent is nil", func(t *testing.T) {
- r := "fallback reasoning"
- msg := Message{Reasoning: &r}
- require.Equal(t, "fallback reasoning", msg.GetReasoningContent())
- })
- t.Run("empty string values returned correctly", func(t *testing.T) {
- empty := ""
- msg := Message{ReasoningContent: &empty}
- require.Equal(t, "", msg.GetReasoningContent())
- })
- }
|