234 lines
6.2 KiB
Go
234 lines
6.2 KiB
Go
package trace
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"log/slog"
|
|
"testing"
|
|
|
|
"github.com/d1nch8g/jules/chat"
|
|
"github.com/d1nch8g/jules/database"
|
|
"github.com/d1nch8g/jules/engine/actions"
|
|
"github.com/d1nch8g/jules/engine/user"
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func captureLog(fn func()) string {
|
|
var buf bytes.Buffer
|
|
handler := slog.NewJSONHandler(&buf, nil)
|
|
logger := slog.New(handler)
|
|
slog.SetDefault(logger)
|
|
fn()
|
|
return buf.String()
|
|
}
|
|
|
|
func TestFromMessage_Log(t *testing.T) {
|
|
msg := chat.Message{
|
|
Chat: "telegram",
|
|
ID: "123456789",
|
|
Text: "Hello, Jules!",
|
|
}
|
|
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), msg).Info("message processed")
|
|
})
|
|
|
|
assert.Contains(t, output, "message processed")
|
|
assert.Contains(t, output, "message_processing")
|
|
assert.Contains(t, output, "telegram")
|
|
assert.Contains(t, output, "123456789")
|
|
assert.Contains(t, output, "Hello, Jules!")
|
|
assert.Contains(t, output, "duration")
|
|
}
|
|
|
|
func TestFromNotification_Log(t *testing.T) {
|
|
notif := database.Notification{
|
|
ID: uuid.New(),
|
|
UserID: uuid.New(),
|
|
InitiatorID: uuid.New(),
|
|
Content: "call mom",
|
|
}
|
|
|
|
output := captureLog(func() {
|
|
FromNotification(context.Background(), notif).Info("notification processed")
|
|
})
|
|
|
|
assert.Contains(t, output, "notification processed")
|
|
assert.Contains(t, output, "notification_processing")
|
|
assert.Contains(t, output, notif.ID.String())
|
|
assert.Contains(t, output, notif.UserID.String())
|
|
assert.Contains(t, output, notif.InitiatorID.String())
|
|
assert.Contains(t, output, "call mom")
|
|
assert.Contains(t, output, "duration")
|
|
}
|
|
|
|
func TestSpan_User_Log(t *testing.T) {
|
|
u := &user.User{
|
|
User: &database.User{
|
|
ID: uuid.New(),
|
|
Language: "ru",
|
|
Timezone: "Europe/Moscow",
|
|
PreferredChat: "telegram",
|
|
Role: "free",
|
|
},
|
|
Chats: []database.Chat{
|
|
{Platform: "telegram"},
|
|
{Platform: "whatsapp"},
|
|
},
|
|
Facts: []database.Fact{
|
|
{Value: "fact1"},
|
|
{Value: "fact2"},
|
|
},
|
|
Contacts: []database.Contact{
|
|
{Name: "Mom"},
|
|
},
|
|
IncomingNotifications: []database.Notification{
|
|
{Content: "incoming1"},
|
|
},
|
|
OutgoingNotifications: []database.Notification{
|
|
{Content: "outgoing1"},
|
|
},
|
|
RecentActions: []database.Action{
|
|
{Payload: json.RawMessage(`{"type":"reply"}`)},
|
|
},
|
|
}
|
|
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), chat.Message{}).User(u).Info("user enriched")
|
|
})
|
|
|
|
assert.Contains(t, output, "user enriched")
|
|
assert.Contains(t, output, u.ID.String())
|
|
assert.Contains(t, output, "ru")
|
|
assert.Contains(t, output, "Europe/Moscow")
|
|
assert.Contains(t, output, "free")
|
|
assert.Contains(t, output, "telegram")
|
|
assert.Contains(t, output, "whatsapp")
|
|
assert.Contains(t, output, "fact1")
|
|
assert.Contains(t, output, "fact2")
|
|
assert.Contains(t, output, "Mom")
|
|
assert.Contains(t, output, "incoming1")
|
|
assert.Contains(t, output, "outgoing1")
|
|
assert.Contains(t, output, "reply")
|
|
assert.Contains(t, output, "duration")
|
|
}
|
|
|
|
func TestSpan_User_Nil(t *testing.T) {
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), chat.Message{}).User(nil).Info("nil user")
|
|
})
|
|
|
|
assert.Contains(t, output, "nil user")
|
|
assert.NotContains(t, output, "user_lang")
|
|
}
|
|
|
|
func TestSpan_User_NilUser(t *testing.T) {
|
|
u := &user.User{User: nil}
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), chat.Message{}).User(u).Info("nil inner user")
|
|
})
|
|
|
|
assert.Contains(t, output, "nil inner user")
|
|
assert.NotContains(t, output, "user_lang")
|
|
}
|
|
|
|
func TestSpan_LLMResponse(t *testing.T) {
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), chat.Message{}).
|
|
LLMResponse("first").
|
|
LLMResponse("second").
|
|
Info("llm response logged")
|
|
})
|
|
|
|
assert.Contains(t, output, "llm response logged")
|
|
assert.Contains(t, output, "llm_response")
|
|
assert.Contains(t, output, "second")
|
|
assert.NotContains(t, output, "first")
|
|
}
|
|
|
|
func TestSpan_Actions(t *testing.T) {
|
|
acts := []actions.Action{
|
|
actions.AddFact{Type: "add_fact", Value: "test fact"},
|
|
actions.Message{Type: "message", Platform: "telegram", Text: "hello"},
|
|
}
|
|
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), chat.Message{}).
|
|
Actions(acts).
|
|
Info("actions logged")
|
|
})
|
|
|
|
assert.Contains(t, output, "actions logged")
|
|
assert.Contains(t, output, "add_fact")
|
|
assert.Contains(t, output, "test fact")
|
|
assert.Contains(t, output, "message")
|
|
assert.Contains(t, output, "telegram")
|
|
assert.Contains(t, output, "hello")
|
|
}
|
|
|
|
func TestSpan_Actions_ReplacesPrevious(t *testing.T) {
|
|
first := []actions.Action{actions.AddFact{Type: "add_fact", Value: "first"}}
|
|
second := []actions.Action{actions.Message{Type: "message", Platform: "telegram", Text: "second"}}
|
|
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), chat.Message{}).
|
|
Actions(first).
|
|
Actions(second).
|
|
Info("actions replaced")
|
|
})
|
|
|
|
assert.Contains(t, output, "actions replaced")
|
|
assert.NotContains(t, output, "first")
|
|
assert.Contains(t, output, "second")
|
|
}
|
|
|
|
func TestSpan_Warn_WithErrors(t *testing.T) {
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), chat.Message{}).
|
|
Warn("warning message", errors.New("err1"), errors.New("err2"))
|
|
})
|
|
|
|
assert.Contains(t, output, "warning message")
|
|
assert.Contains(t, output, "WARN")
|
|
assert.Contains(t, output, "err1")
|
|
assert.Contains(t, output, "err2")
|
|
assert.Contains(t, output, "duration")
|
|
}
|
|
|
|
func TestSpan_Warn_NoErrors(t *testing.T) {
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), chat.Message{}).
|
|
Warn("warning without errors")
|
|
})
|
|
|
|
assert.Contains(t, output, "warning without errors")
|
|
assert.Contains(t, output, "WARN")
|
|
assert.NotContains(t, output, "\"error\"")
|
|
}
|
|
|
|
func TestSpan_Error(t *testing.T) {
|
|
output := captureLog(func() {
|
|
FromMessage(context.Background(), chat.Message{}).
|
|
Error("error message", errors.New("fatal"))
|
|
})
|
|
|
|
assert.Contains(t, output, "error message")
|
|
assert.Contains(t, output, "ERROR")
|
|
assert.Contains(t, output, "fatal")
|
|
assert.Contains(t, output, "duration")
|
|
}
|
|
|
|
func TestSpan_Log_NoContext(t *testing.T) {
|
|
output := captureLog(func() {
|
|
s := FromMessage(context.Background(), chat.Message{Chat: "telegram", ID: "123", Text: "hi"})
|
|
s.ctx = nil
|
|
s.Info("no context")
|
|
})
|
|
|
|
assert.Contains(t, output, "no context")
|
|
assert.Contains(t, output, "duration")
|
|
}
|