Support direct freeform create for upload fact-source registration while keeping source_content_sha256 as a content fingerprint only. Co-authored-by: Cursor <cursoragent@cursor.com>
125 lines
4.3 KiB
Go
125 lines
4.3 KiB
Go
package freedoc_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"chat-agent-system/internal/ctxmgr"
|
|
"chat-agent-system/internal/freedoc"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestFreeformDocService_LifecycleAndACL(t *testing.T) {
|
|
ctx := context.Background()
|
|
ctxMgr := ctxmgr.NewContextManager(nil, nil, ctxmgr.DefaultTimeDecayConfig())
|
|
service := freedoc.NewService(nil, ctxMgr)
|
|
|
|
// 1. 录入一条助手有效消息
|
|
sessionID := "sess-test-freedoc"
|
|
asstMsgID, err := ctxMgr.RecordUserMessageWithID(ctx, sessionID, 1, "assistant", "# 临床风险评价\n\n依据 GB 9706.1 进行耐压评估,结果合格。", "consult", "main", nil)
|
|
require.NoError(t, err)
|
|
|
|
// 2. 录入一条纯卡片消息(不可导出)
|
|
cardOnlyMsgID, err := ctxMgr.RecordUserMessageWithID(ctx, sessionID, 1, "assistant", "请确认以下操作", "consult", "main", map[string]any{
|
|
"interactive_card": map[string]any{"card_id": "card-1"},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// 3. 尝试从纯卡片创建私密文档 -> 应该拒绝
|
|
_, _, err = service.CreateFromMessage(ctx, 101, freedoc.CreateFromMessageRequest{
|
|
MessageID: cardOnlyMsgID,
|
|
ProjectID: 1,
|
|
})
|
|
assert.ErrorIs(t, err, freedoc.ErrMessageNotExportable)
|
|
|
|
// 4. 从正常消息创建私密文档 -> 成功
|
|
detail, isExisting, err := service.CreateFromMessage(ctx, 101, freedoc.CreateFromMessageRequest{
|
|
MessageID: asstMsgID,
|
|
ProjectID: 1,
|
|
})
|
|
require.NoError(t, err)
|
|
assert.False(t, isExisting)
|
|
assert.Equal(t, "临床风险评价", detail.Document.Title)
|
|
assert.Equal(t, "my_private", detail.Document.Space)
|
|
assert.Equal(t, 1, detail.Document.CurrentVersionID)
|
|
assert.Contains(t, detail.Content, "依据 GB 9706.1")
|
|
docID := detail.Document.DocID
|
|
|
|
// 5. 幂等性测试:同一用户针对同一消息再次保存 -> 直接返回已有文档
|
|
detail2, isExisting2, err := service.CreateFromMessage(ctx, 101, freedoc.CreateFromMessageRequest{
|
|
MessageID: asstMsgID,
|
|
ProjectID: 1,
|
|
})
|
|
require.NoError(t, err)
|
|
assert.True(t, isExisting2)
|
|
assert.Equal(t, docID, detail2.Document.DocID)
|
|
|
|
// 6. 私密文档访问隔离红线测试:
|
|
// Owner 访问 -> 成功
|
|
ownerDoc, err := service.GetDocument(ctx, 101, docID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, docID, ownerDoc.Document.DocID)
|
|
|
|
// 其他用户(哪怕管理员)访问私密文档 -> 严格拒绝 ErrForbidden
|
|
_, err = service.GetDocument(ctx, 999, docID)
|
|
assert.ErrorIs(t, err, freedoc.ErrForbidden)
|
|
|
|
// 7. 列表隔离测试
|
|
listUser101, err := service.ListDocuments(ctx, 101, 1, "my_private")
|
|
require.NoError(t, err)
|
|
assert.Len(t, listUser101, 1)
|
|
|
|
listUser999, err := service.ListDocuments(ctx, 999, 1, "my_private")
|
|
require.NoError(t, err)
|
|
assert.Empty(t, listUser999)
|
|
|
|
// 8. 乐观并发控制与编辑测试
|
|
// 期望版本不匹配 -> ErrConflict
|
|
badVer := 99
|
|
newContent := "更新后的正文内容"
|
|
_, err = service.UpdateDocument(ctx, 101, docID, freedoc.UpdateFreeformDocRequest{
|
|
ContentMarkdown: &newContent,
|
|
ExpectedVersion: &badVer,
|
|
})
|
|
assert.ErrorIs(t, err, freedoc.ErrConflict)
|
|
|
|
// 正常版本更新 -> 生成版本 2
|
|
curVer := 1
|
|
updated, err := service.UpdateDocument(ctx, 101, docID, freedoc.UpdateFreeformDocRequest{
|
|
ContentMarkdown: &newContent,
|
|
ExpectedVersion: &curVer,
|
|
ChangeSummary: "修订正文说明",
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 2, updated.Document.CurrentVersionID)
|
|
assert.Equal(t, "更新后的正文内容", updated.Content)
|
|
|
|
// 9. 共享到项目参考库 (Share)
|
|
sharedDoc, err := service.ShareDocument(ctx, 101, docID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "project_shared", sharedDoc.Space)
|
|
|
|
// 共享后,项目成员 999 可以在共享库中读取
|
|
sharedDetail, err := service.GetDocument(ctx, 999, docID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, docID, sharedDetail.Document.DocID)
|
|
|
|
// 10. 撤回共享 (Unshare)
|
|
unsharedDoc, err := service.UnshareDocument(ctx, 101, docID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "my_private", unsharedDoc.Space)
|
|
|
|
// 撤回后,用户 999 再次读取 -> 立即重新拦截 ErrForbidden
|
|
_, err = service.GetDocument(ctx, 999, docID)
|
|
assert.ErrorIs(t, err, freedoc.ErrForbidden)
|
|
|
|
// 11. 删除文档 (Delete)
|
|
err = service.DeleteDocument(ctx, 101, docID)
|
|
require.NoError(t, err)
|
|
|
|
// 删除后再获取 -> ErrNotFound
|
|
_, err = service.GetDocument(ctx, 101, docID)
|
|
assert.ErrorIs(t, err, freedoc.ErrNotFound)
|
|
}
|